chore: split logs and annotations page

This commit is contained in:
Joel
2026-06-02 11:01:38 +08:00
parent 2d6fd70733
commit 1ac3ad4c81
30 changed files with 152 additions and 104 deletions

View File

@ -67,7 +67,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
const res = appDetailRes
// redirection
const canIEditApp = isCurrentWorkspaceEditor
if (!canIEditApp && (pathname.endsWith('configuration') || pathname.endsWith('workflow') || pathname.endsWith('logs'))) {
if (!canIEditApp && (pathname.endsWith('configuration') || pathname.endsWith('workflow') || pathname.endsWith('logs') || pathname.endsWith('annotations'))) {
router.replace(`/app/${appId}/overview`)
return
}

View File

@ -0,0 +1,93 @@
import { render, screen } from '@testing-library/react'
import AppDetailSection from '../app-detail-section'
let mockAppMode = 'chat'
let mockIsCurrentWorkspaceEditor = true
vi.mock('@/app/components/app/store', () => ({
useStore: (selector: (state: Record<string, unknown>) => unknown) => selector({
appDetail: {
id: 'app-1',
name: 'Test App',
mode: mockAppMode,
icon: '🤖',
icon_type: 'emoji',
icon_background: '#fff',
},
}),
}))
vi.mock('@/context/app-context', () => ({
useAppContext: () => ({
isCurrentWorkspaceEditor: mockIsCurrentWorkspaceEditor,
}),
}))
vi.mock('@/next/navigation', () => ({
usePathname: () => '/app/app-1/logs',
}))
vi.mock('../app-info', () => ({
AppInfoView: () => <div data-testid="app-info" />,
}))
vi.mock('../app-info/use-app-info-actions', () => ({
useAppInfoActions: () => ({}),
}))
vi.mock('../../base/divider', () => ({
default: () => <hr />,
}))
vi.mock('../nav-link', () => ({
default: ({ name, href }: { name: string, href: string }) => (
<a href={href}>{name}</a>
),
}))
describe('AppDetailSection', () => {
beforeEach(() => {
vi.clearAllMocks()
mockAppMode = 'chat'
mockIsCurrentWorkspaceEditor = true
})
// Rendering behavior for app detail navigation entries.
describe('Rendering', () => {
it('should split logs and annotations into separate navigation links for chat apps', () => {
// Arrange
mockAppMode = 'chat'
// Act
render(<AppDetailSection />)
// Assert
expect(screen.getByRole('link', { name: 'common.appMenus.logs' })).toHaveAttribute('href', '/app/app-1/logs')
expect(screen.getByRole('link', { name: 'common.appMenus.annotations' })).toHaveAttribute('href', '/app/app-1/annotations')
})
it('should only render logs navigation for workflow apps', () => {
// Arrange
mockAppMode = 'workflow'
// Act
render(<AppDetailSection />)
// Assert
expect(screen.getByRole('link', { name: 'common.appMenus.logs' })).toHaveAttribute('href', '/app/app-1/logs')
expect(screen.queryByRole('link', { name: 'common.appMenus.annotations' })).not.toBeInTheDocument()
})
it('should only render logs navigation for completion apps', () => {
// Arrange
mockAppMode = 'completion'
// Act
render(<AppDetailSection />)
// Assert
expect(screen.getByRole('link', { name: 'common.appMenus.logs' })).toHaveAttribute('href', '/app/app-1/logs')
expect(screen.queryByRole('link', { name: 'common.appMenus.annotations' })).not.toBeInTheDocument()
})
})
})

View File

@ -6,6 +6,8 @@ import {
RiDashboard2Line,
RiFileList3Fill,
RiFileList3Line,
RiStickyNoteFill,
RiStickyNoteLine,
RiTerminalBoxFill,
RiTerminalBoxLine,
RiTerminalWindowFill,
@ -44,6 +46,7 @@ const AppDetailSection = () => {
const appId = appDetail.id
const isWorkflowApp = appDetail.mode === AppModeEnum.WORKFLOW || appDetail.mode === AppModeEnum.ADVANCED_CHAT
const supportsAnnotations = appDetail.mode !== AppModeEnum.WORKFLOW && appDetail.mode !== AppModeEnum.COMPLETION
return [
...(isCurrentWorkspaceEditor
@ -63,13 +66,18 @@ const AppDetailSection = () => {
},
...(isCurrentWorkspaceEditor
? [{
name: appDetail.mode !== AppModeEnum.WORKFLOW
? t('appMenus.logAndAnn', { ns: 'common' })
: t('appMenus.logs', { ns: 'common' }),
name: t('appMenus.logs', { ns: 'common' }),
href: `/app/${appId}/logs`,
icon: RiFileList3Line,
selectedIcon: RiFileList3Fill,
}]
}, ...(supportsAnnotations
? [{
name: t('appMenus.annotations', { ns: 'common' }),
href: `/app/${appId}/annotations`,
icon: RiStickyNoteLine,
selectedIcon: RiStickyNoteFill,
}]
: [])]
: []
),
{

View File

@ -211,7 +211,7 @@ describe('NavLink Animation and Layout Issues', () => {
expect(linkElement).toHaveClass('text-text-accent-light-mode-only')
})
it('should use pathname when rendered outside the app detail route segment', () => {
it('should not mark logs active on the annotations pathname', () => {
render(
<NavLink
{...mockProps}
@ -220,6 +220,19 @@ describe('NavLink Animation and Layout Issues', () => {
/>,
)
const linkElement = screen.getByRole('link', { name: 'Orchestrate' })
expect(linkElement).not.toHaveClass('bg-components-menu-item-bg-active')
})
it('should use pathname to mark annotations active when rendered outside the app detail route segment', () => {
render(
<NavLink
{...mockProps}
href="/app/123/annotations"
pathname="/app/123/annotations"
/>,
)
const linkElement = screen.getByRole('link', { name: 'Orchestrate' })
expect(linkElement).toHaveClass('bg-components-menu-item-bg-active')
})

View File

@ -33,14 +33,7 @@ const NavLink = ({
pathname,
}: NavLinkProps) => {
const segment = useSelectedLayoutSegment()
const formattedSegment = (() => {
let res = pathname ? pathname.toLowerCase().split('/').filter(Boolean).pop() : segment?.toLowerCase()
// logs and annotations use the same nav
if (res === 'annotations')
res = 'logs'
return res
})()
const formattedSegment = pathname ? pathname.toLowerCase().split('/').filter(Boolean).pop() : segment?.toLowerCase()
const isActive = href.toLowerCase().split('/')?.pop() === formattedSegment
const NavIcon = isActive ? iconMap.selected : iconMap.normal

View File

@ -1,18 +1,10 @@
import type { App, AppIconType } from '@/types/app'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useStore as useAppStore } from '@/app/components/app/store'
import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type'
import { AppModeEnum } from '@/types/app'
import LogAnnotation from '../index'
const mockRouterPush = vi.fn()
vi.mock('@/next/navigation', () => ({
useRouter: () => ({
push: mockRouterPush,
}),
}))
vi.mock('@/app/components/app/annotation', () => ({
default: ({ appDetail }: { appDetail: App }) => (
<section aria-label="Annotation log">{appDetail.id}</section>
@ -80,7 +72,7 @@ describe('LogAnnotation', () => {
expect(screen.getByRole('status')).toBeInTheDocument()
})
it('should render log and annotation tabs for non-completion apps', () => {
it('should render log content without the old page tabs', () => {
// Arrange
useAppStore.setState({ appDetail: createMockApp({ mode: AppModeEnum.CHAT }) })
@ -88,11 +80,12 @@ describe('LogAnnotation', () => {
render(<LogAnnotation pageType={PageType.log} />)
// Assert
expect(screen.getByText('appLog.title')).toBeInTheDocument()
expect(screen.getByText('appAnnotation.title')).toBeInTheDocument()
expect(screen.getByRole('region', { name: 'App log' })).toBeInTheDocument()
expect(screen.queryByText('appLog.title')).not.toBeInTheDocument()
expect(screen.queryByText('appAnnotation.title')).not.toBeInTheDocument()
})
it('should render only log tab for completion apps', () => {
it('should render completion logs without the old page tabs', () => {
// Arrange
useAppStore.setState({ appDetail: createMockApp({ mode: AppModeEnum.COMPLETION }) })
@ -100,7 +93,8 @@ describe('LogAnnotation', () => {
render(<LogAnnotation pageType={PageType.log} />)
// Assert
expect(screen.getByText('appLog.title')).toBeInTheDocument()
expect(screen.getByRole('region', { name: 'App log' })).toBeInTheDocument()
expect(screen.queryByText('appLog.title')).not.toBeInTheDocument()
expect(screen.queryByText('appAnnotation.title')).not.toBeInTheDocument()
})
@ -143,31 +137,4 @@ describe('LogAnnotation', () => {
expect(screen.queryByRole('region', { name: 'App log' })).not.toBeInTheDocument()
})
})
// User interaction behavior
describe('User Interactions', () => {
it('should navigate to annotations when switching from log tab', async () => {
// Arrange
const user = userEvent.setup()
// Act
render(<LogAnnotation pageType={PageType.log} />)
await user.click(screen.getByText('appAnnotation.title'))
// Assert
expect(mockRouterPush).toHaveBeenCalledWith('/app/app-123/annotations')
})
it('should navigate to logs when switching from annotation tab', async () => {
// Arrange
const user = userEvent.setup()
// Act
render(<LogAnnotation pageType={PageType.annotation} />)
await user.click(screen.getByText('appLog.title'))
// Assert
expect(mockRouterPush).toHaveBeenCalledWith('/app/app-123/logs')
})
})
})

View File

@ -1,17 +1,12 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Annotation from '@/app/components/app/annotation'
import Log from '@/app/components/app/log'
import { useStore as useAppStore } from '@/app/components/app/store'
import WorkflowLog from '@/app/components/app/workflow-log'
import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type'
import Loading from '@/app/components/base/loading'
import TabSlider from '@/app/components/base/tab-slider-plain'
import { useRouter } from '@/next/navigation'
import { AppModeEnum } from '@/types/app'
type Props = {
@ -21,19 +16,8 @@ type Props = {
const LogAnnotation: FC<Props> = ({
pageType,
}) => {
const { t } = useTranslation()
const router = useRouter()
const appDetail = useAppStore(state => state.appDetail)
const options = useMemo(() => {
if (appDetail?.mode === AppModeEnum.COMPLETION)
return [{ value: PageType.log, text: t('title', { ns: 'appLog' }) }]
return [
{ value: PageType.log, text: t('title', { ns: 'appLog' }) },
{ value: PageType.annotation, text: t('title', { ns: 'appAnnotation' }) },
]
}, [appDetail?.mode, t])
if (!appDetail) {
return (
<div className="flex h-full items-center justify-center bg-background-body">
@ -44,17 +28,7 @@ const LogAnnotation: FC<Props> = ({
return (
<div className="flex h-full flex-col px-6 pt-3">
{appDetail.mode !== AppModeEnum.WORKFLOW && (
<TabSlider
className="shrink-0"
value={pageType}
onChange={(value) => {
router.push(`/app/${appDetail.id}/${value === PageType.log ? 'logs' : 'annotations'}`)
}}
options={options}
/>
)}
<div className={cn('h-0 grow', appDetail.mode !== AppModeEnum.WORKFLOW && 'mt-3')}>
<div className="h-0 grow">
{pageType === PageType.log && appDetail.mode !== AppModeEnum.WORKFLOW && (<Log appDetail={appDetail} />)}
{pageType === PageType.annotation && (<Annotation appDetail={appDetail} />)}
{pageType === PageType.log && appDetail.mode === AppModeEnum.WORKFLOW && (<WorkflowLog appDetail={appDetail} />)}

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "توفر ملحقات API إدارة مركزية لواجهة برمجة التطبيقات، مما يبسط التكوين لسهولة الاستخدام عبر تطبيقات Dify.",
"apiBasedExtension.type": "النوع",
"apiBasedExtensionPage.description": "وسّع قدرات وحدات Dify عبر API — أضف إشرافًا مخصصًا على المحتوى أو أدوات بيانات خارجية إلى تطبيقاتك.",
"appMenus.annotations": "التعليقات التوضيحية",
"appMenus.apiAccess": "وصول API",
"appMenus.apiAccessTip": "يمكن الوصول إلى قاعدة المعرفة هذه عبر واجهة برمجة تطبيقات الخدمة",
"appMenus.logAndAnn": "السجلات والتعليقات التوضيحية",
"appMenus.logs": "السجلات",
"appMenus.overview": "المراقبة",
"appMenus.promptEng": "تنسيق",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API-Erweiterungen bieten zentralisiertes API-Management und vereinfachen die Konfiguration für eine einfache Verwendung in Difys Anwendungen.",
"apiBasedExtension.type": "Typ",
"apiBasedExtensionPage.description": "Erweitere die Modulfunktionen von Dify per API — füge deinen Apps benutzerdefinierte Inhaltsmoderation oder externe Datentools hinzu.",
"appMenus.annotations": "Anmerkungen",
"appMenus.apiAccess": "API-Zugriff",
"appMenus.apiAccessTip": "Diese Wissensdatenbank ist über die Service-API zugänglich",
"appMenus.logAndAnn": "Protokolle & Ank.",
"appMenus.logs": "Baumstämme",
"appMenus.overview": "Übersicht",
"appMenus.promptEng": "Orchestrieren",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API Extensions provide centralized API management, simplifying configuration for easy use across Dify's applications.",
"apiBasedExtension.type": "Type",
"apiBasedExtensionPage.description": "Extend Dify's module capabilities via API — add custom content moderation or external data tools to your apps.",
"appMenus.annotations": "Annotations",
"appMenus.apiAccess": "API Access",
"appMenus.apiAccessTip": "This knowledge base is accessible via the Service API",
"appMenus.logAndAnn": "Logs & Annotations",
"appMenus.logs": "Logs",
"appMenus.overview": "Monitoring",
"appMenus.promptEng": "Orchestrate",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Las extensiones basadas en API proporcionan una gestión centralizada de API, simplificando la configuración para su fácil uso en las aplicaciones de Dify.",
"apiBasedExtension.type": "Tipo",
"apiBasedExtensionPage.description": "Amplía las capacidades de los módulos de Dify mediante API: añade moderación de contenido personalizada o herramientas de datos externas a tus apps.",
"appMenus.annotations": "Anotaciones",
"appMenus.apiAccess": "Acceso API",
"appMenus.apiAccessTip": "Esta base de conocimiento es accesible a través de la API de servicio",
"appMenus.logAndAnn": "Registros y Anuncios",
"appMenus.logs": "Registros",
"appMenus.overview": "Monitoreo",
"appMenus.promptEng": "Orquestar",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "افزونه‌های مبتنی بر API مدیریت متمرکز API را فراهم می‌کنند و پیکربندی را برای استفاده آسان در برنامه‌های Dify ساده می‌کنند.",
"apiBasedExtension.type": "نوع",
"apiBasedExtensionPage.description": "قابلیت‌های ماژول‌های Dify را از طریق API گسترش دهید — بازبینی محتوای سفارشی یا ابزارهای داده خارجی را به برنامه‌های خود اضافه کنید.",
"appMenus.annotations": "یادداشت‌ها",
"appMenus.apiAccess": "دسترسی API",
"appMenus.apiAccessTip": "این پایگاه دانش از طریق API سرویس قابل دسترسی است",
"appMenus.logAndAnn": "گزارش‌ها و اعلانات",
"appMenus.logs": "گزارش‌ها",
"appMenus.overview": "نظارت",
"appMenus.promptEng": "هماهنگ‌سازی",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Les extensions API fournissent une gestion centralisée des API, simplifiant la configuration pour une utilisation facile à travers les applications de Dify.",
"apiBasedExtension.type": "Tapez",
"apiBasedExtensionPage.description": "Étendez les capacités des modules de Dify via API — ajoutez une modération de contenu personnalisée ou des outils de données externes à vos apps.",
"appMenus.annotations": "Annotations",
"appMenus.apiAccess": "Accès API",
"appMenus.apiAccessTip": "Cette base de connaissances est accessible via l'API de service",
"appMenus.logAndAnn": "Journaux & Annonces.",
"appMenus.logs": "Journaux",
"appMenus.overview": "Surveillance",
"appMenus.promptEng": "Orchestrer",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "एपीआई एक्सटेंशन केंद्रीकृत एपीआई प्रबंधन प्रदान करते हैं, जो Dify के अनुप्रयोगों में आसान उपयोग के लिए कॉन्फ़िगरेशन को सरल बनाते हैं।",
"apiBasedExtension.type": "प्रकार",
"apiBasedExtensionPage.description": "API के ज़रिये Dify की मॉड्यूल क्षमताओं को बढ़ाएँ — अपने ऐप्स में कस्टम कंटेंट मॉडरेशन या बाहरी डेटा टूल जोड़ें।",
"appMenus.annotations": "एनोटेशन",
"appMenus.apiAccess": "API एक्सेस",
"appMenus.apiAccessTip": "यह ज्ञान आधार सेवा API के माध्यम से सुलभ है",
"appMenus.logAndAnn": "लॉग्स और घोषणाएँ",
"appMenus.logs": "लॉग्स",
"appMenus.overview": "निगरानी",
"appMenus.promptEng": "समन्वय करें",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Ekstensi API menyediakan manajemen API terpusat, menyederhanakan konfigurasi agar mudah digunakan di seluruh aplikasi Dify.",
"apiBasedExtension.type": "Jenis",
"apiBasedExtensionPage.description": "Perluas kemampuan modul Dify melalui API — tambahkan moderasi konten khusus atau alat data eksternal ke aplikasi Anda.",
"appMenus.annotations": "Anotasi",
"appMenus.apiAccess": "Akses API",
"appMenus.apiAccessTip": "Basis pengetahuan ini dapat diakses melalui API layanan",
"appMenus.logAndAnn": "Log & Anotasi",
"appMenus.logs": "Log",
"appMenus.overview": "Pemantauan",
"appMenus.promptEng": "Mengatur",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Le estensioni API forniscono una gestione centralizzata delle API, semplificando la configurazione per un facile utilizzo nelle applicazioni di Dify.",
"apiBasedExtension.type": "Tipo",
"apiBasedExtensionPage.description": "Estendi le capacità dei moduli di Dify tramite API — aggiungi moderazione dei contenuti personalizzata o strumenti dati esterni alle tue app.",
"appMenus.annotations": "Annotazioni",
"appMenus.apiAccess": "Accesso API",
"appMenus.apiAccessTip": "Questa base di conoscenza è accessibile tramite l'API del servizio",
"appMenus.logAndAnn": "Log & Ann.",
"appMenus.logs": "Log",
"appMenus.overview": "Monitoraggio",
"appMenus.promptEng": "Orchestrazione",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API 拡張機能は、Dify のアプリケーション全体での簡単な使用のための設定を簡素化し、集中的な API 管理を提供します。",
"apiBasedExtension.type": "タイプ",
"apiBasedExtensionPage.description": "API を通じて Dify のモジュール機能を拡張——カスタムのコンテンツモデレーションや外部データツールをアプリに追加できます。",
"appMenus.annotations": "注釈",
"appMenus.apiAccess": "API アクセス",
"appMenus.apiAccessTip": "このナレッジベースはサービスAPIを介してアクセス可能です",
"appMenus.logAndAnn": "ログ&注釈",
"appMenus.logs": "ログ",
"appMenus.overview": "監視",
"appMenus.promptEng": "オーケストレート",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API 기반 확장은 Dify 애플리케이션 전체에서 간편한 사용을 위한 설정을 단순화하고 집중적인 API 관리를 제공합니다.",
"apiBasedExtension.type": "유형",
"apiBasedExtensionPage.description": "API를 통해 Dify의 모듈 기능을 확장하고, 앱에 맞춤형 콘텐츠 검수 또는 외부 데이터 도구를 추가하세요.",
"appMenus.annotations": "어노테이션",
"appMenus.apiAccess": "API 액세스",
"appMenus.apiAccessTip": "이 지식 베이스는 서비스 API를 통해 액세스할 수 있습니다",
"appMenus.logAndAnn": "로그 및 어노테이션",
"appMenus.logs": "로그",
"appMenus.overview": "모니터링",
"appMenus.promptEng": "오케스트레이트",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API extensions provide centralized API management, simplifying configuration for easy use across Dify's applications.",
"apiBasedExtension.type": "Type",
"apiBasedExtensionPage.description": "Breid de modulemogelijkheden van Dify uit via API — voeg aangepaste contentmoderatie of externe datatools toe aan je apps.",
"appMenus.annotations": "Annotations",
"appMenus.apiAccess": "API Access",
"appMenus.apiAccessTip": "This knowledge base is accessible via the Service API",
"appMenus.logAndAnn": "Logs & Annotations",
"appMenus.logs": "Logs",
"appMenus.overview": "Monitoring",
"appMenus.promptEng": "Orchestrate",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Rozszerzenia oparte na interfejsie API zapewniają scentralizowane zarządzanie interfejsami API, upraszczając konfigurację dla łatwego użytkowania w aplikacjach Dify.",
"apiBasedExtension.type": "Typ",
"apiBasedExtensionPage.description": "Rozszerz możliwości modułów Dify przez API — dodaj do aplikacji niestandardową moderację treści lub zewnętrzne narzędzia danych.",
"appMenus.annotations": "Adnotacje",
"appMenus.apiAccess": "Dostęp API",
"appMenus.apiAccessTip": "Ta baza wiedzy jest dostępna przez API usługi",
"appMenus.logAndAnn": "Logi i ogł.",
"appMenus.logs": "Logi",
"appMenus.overview": "Monitorowanie",
"appMenus.promptEng": "Orkiestracja",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "As extensões de API fornecem gerenciamento centralizado de API, simplificando a configuração para uso fácil em todos os aplicativos da Dify.",
"apiBasedExtension.type": "Tipo",
"apiBasedExtensionPage.description": "Amplie os recursos dos módulos do Dify via API — adicione moderação de conteúdo personalizada ou ferramentas de dados externas aos seus apps.",
"appMenus.annotations": "Anotações",
"appMenus.apiAccess": "Acesso à API",
"appMenus.apiAccessTip": "Esta base de conhecimento é acessível via API de serviço",
"appMenus.logAndAnn": "Logs e Anúncios",
"appMenus.logs": "Logs",
"appMenus.overview": "Monitoramento",
"appMenus.promptEng": "Orquestrar",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Extensiile bazate pe API oferă o gestionare centralizată a API-urilor, simplificând configurația pentru o utilizare ușoară în aplicațiile Dify.",
"apiBasedExtension.type": "Tip",
"apiBasedExtensionPage.description": "Extinde capabilitățile modulelor Dify prin API — adaugă în aplicații moderare de conținut personalizată sau instrumente externe de date.",
"appMenus.annotations": "Anotări",
"appMenus.apiAccess": "Acces API",
"appMenus.apiAccessTip": "Această bază de cunoștințe este accesibilă prin API-ul serviciului",
"appMenus.logAndAnn": "Jurnale și Ann.",
"appMenus.logs": "Jurnale",
"appMenus.overview": "Monitorizare",
"appMenus.promptEng": "Orchestrare",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API-расширения обеспечивают централизованное управление API, упрощая настройку для удобного использования в приложениях Dify.",
"apiBasedExtension.type": "Тип",
"apiBasedExtensionPage.description": "Расширяйте возможности модулей Dify через API — добавляйте в приложения собственную модерацию контента или внешние инструменты данных.",
"appMenus.annotations": "Аннотации",
"appMenus.apiAccess": "Доступ к API",
"appMenus.apiAccessTip": "Эта база знаний доступна через API сервиса",
"appMenus.logAndAnn": "Журналы и аннотации",
"appMenus.logs": "Журналы",
"appMenus.overview": "Мониторинг",
"appMenus.promptEng": "Оркестрация",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Razširitve API zagotavljajo centralizirano upravljanje API, kar poenostavlja konfiguracijo za enostavno uporabo v aplikacijah Dify.",
"apiBasedExtension.type": "Vrsta",
"apiBasedExtensionPage.description": "Razširite zmožnosti modulov Dify prek API-ja — v aplikacije dodajte prilagojeno moderiranje vsebine ali zunanja podatkovna orodja.",
"appMenus.annotations": "Opombe",
"appMenus.apiAccess": "Dostop do API-ja",
"appMenus.apiAccessTip": "Ta baza znanja je dostopna prek API storitve",
"appMenus.logAndAnn": "Dnevniki & Ann.",
"appMenus.logs": "Dnevniki",
"appMenus.overview": "Spremljanje",
"appMenus.promptEng": "Orkester",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "ส่วนขยาย API ให้การจัดการ API แบบรวมศูนย์ ทําให้การกําหนดค่าง่ายขึ้นเพื่อให้ใช้งานได้ง่ายในแอปพลิเคชันของ Dify",
"apiBasedExtension.type": "ประเภท",
"apiBasedExtensionPage.description": "ขยายความสามารถของโมดูล Dify ผ่าน API — เพิ่มการตรวจสอบเนื้อหาแบบกำหนดเองหรือเครื่องมือข้อมูลภายนอกให้แอปของคุณ",
"appMenus.annotations": "คำ อธิบาย",
"appMenus.apiAccess": "การเข้าถึง API",
"appMenus.apiAccessTip": "ฐานความรู้นี้สามารถเข้าถึงได้ผ่าน API บริการ",
"appMenus.logAndAnn": "ล็อก & แอน.",
"appMenus.logs": "บันทึก",
"appMenus.overview": "ตรวจ สอบ",
"appMenus.promptEng": "ออเคสตร้า",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API uzantıları merkezi API yönetimi sağlar, Dify'nin uygulamaları arasında kolay kullanım için yapılandırmayı basitleştirir.",
"apiBasedExtension.type": "Tür",
"apiBasedExtensionPage.description": "API ile Dify modül yeteneklerini genişletin — uygulamalarınıza özel içerik denetimi veya harici veri araçları ekleyin.",
"appMenus.annotations": "Ek Açıklamalar",
"appMenus.apiAccess": "API Erişimi",
"appMenus.apiAccessTip": "Bu bilgi tabanına Servis API üzerinden erişilebilir",
"appMenus.logAndAnn": "Günlükler & Anlamlandırmalar",
"appMenus.logs": "Günlükler",
"appMenus.overview": "İzleme",
"appMenus.promptEng": "Düzenle",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API-розширення забезпечують централізоване керування API, спрощуючи конфігурацію для зручного використання в різних програмах Dify.",
"apiBasedExtension.type": "Тип",
"apiBasedExtensionPage.description": "Розширюйте можливості модулів Dify через API — додавайте до застосунків власну модерацію контенту або зовнішні інструменти даних.",
"appMenus.annotations": "Анотації",
"appMenus.apiAccess": "Доступ до API",
"appMenus.apiAccessTip": "Ця база знань доступна через API сервісу",
"appMenus.logAndAnn": "Журнали та Повідомлення.",
"appMenus.logs": "Журнали",
"appMenus.overview": "Моніторинг",
"appMenus.promptEng": "Налаштування",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "Các tiện ích API cung cấp quản lý API tập trung, giúp cấu hình dễ dàng sử dụng trên các ứng dụng của Dify.",
"apiBasedExtension.type": "Loại",
"apiBasedExtensionPage.description": "Mở rộng khả năng mô-đun của Dify qua API — thêm kiểm duyệt nội dung tùy chỉnh hoặc công cụ dữ liệu bên ngoài vào ứng dụng của bạn.",
"appMenus.annotations": "Chú thích",
"appMenus.apiAccess": "Truy cập API",
"appMenus.apiAccessTip": "Cơ sở kiến thức này có thể truy cập qua API dịch vụ",
"appMenus.logAndAnn": "Nhật ký & Thông báo",
"appMenus.logs": "Nhật ký",
"appMenus.overview": "Giám sát",
"appMenus.promptEng": "Orchestrate",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API 扩展提供了一个集中式的 API 管理,在此统一添加 API 配置后,方便在 Dify 上的各类应用中直接使用。",
"apiBasedExtension.type": "类型",
"apiBasedExtensionPage.description": "通过 API 扩展 Dify 的模块能力——为应用接入自定义内容审核或外部数据工具。",
"appMenus.annotations": "标注",
"appMenus.apiAccess": "访问 API",
"appMenus.apiAccessTip": "此知识库可通过服务 API 访问",
"appMenus.logAndAnn": "日志与标注",
"appMenus.logs": "日志",
"appMenus.overview": "监测",
"appMenus.promptEng": "编排",

View File

@ -98,9 +98,9 @@
"apiBasedExtension.title": "API 擴充套件提供了一個集中式的 API 管理,在此統一新增 API 配置後,方便在 Dify 上的各類應用中直接使用。",
"apiBasedExtension.type": "型別",
"apiBasedExtensionPage.description": "透過 API 擴充 Dify 的模組能力,為應用新增自訂內容審核或外部資料工具。",
"appMenus.annotations": "標註",
"appMenus.apiAccess": "訪問 API",
"appMenus.apiAccessTip": "此知識庫可透過服務 API 訪問",
"appMenus.logAndAnn": "日誌與標註",
"appMenus.logs": "日誌",
"appMenus.overview": "監控",
"appMenus.promptEng": "編排",