diff --git a/packages/iconify-collections/assets/public/common/confluence.svg b/packages/iconify-collections/assets/public/common/confluence.svg new file mode 100644 index 00000000000..c5b27dd609d --- /dev/null +++ b/packages/iconify-collections/assets/public/common/confluence.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/iconify-collections/custom-public/icons.json b/packages/iconify-collections/custom-public/icons.json index 361e5a7a5bd..ff9d33c6744 100644 --- a/packages/iconify-collections/custom-public/icons.json +++ b/packages/iconify-collections/custom-public/icons.json @@ -1,6 +1,6 @@ { "prefix": "custom-public", - "lastModified": 1783583299, + "lastModified": 1784810412, "icons": { "agent-building-blocks": { "body": "" @@ -65,6 +65,11 @@ "width": 13, "height": 13 }, + "common-confluence": { + "body": "", + "width": 24, + "height": 24 + }, "common-d": { "body": "" }, diff --git a/packages/iconify-collections/custom-public/info.json b/packages/iconify-collections/custom-public/info.json index 818be4086b8..c25fc1912aa 100644 --- a/packages/iconify-collections/custom-public/info.json +++ b/packages/iconify-collections/custom-public/info.json @@ -1,7 +1,7 @@ { "prefix": "custom-public", "name": "Dify Custom Public", - "total": 146, + "total": 147, "version": "0.0.0-private", "author": { "name": "LangGenius, Inc.", diff --git a/web/app/(commonLayout)/datasets/layout.spec.tsx b/web/app/(commonLayout)/datasets/layout.spec.tsx index a5bba0eb2b0..2dd57fedee2 100644 --- a/web/app/(commonLayout)/datasets/layout.spec.tsx +++ b/web/app/(commonLayout)/datasets/layout.spec.tsx @@ -202,39 +202,45 @@ describe('DatasetsLayout', () => { expect(mockReplace).not.toHaveBeenCalled() }) - it('should redirect direct external dataset connection route to /datasets without dataset.external.connect', async () => { - mockPathname = '/datasets/connect' - setConsoleState({ - workspacePermissionKeys: [], - }) + it.each(['/datasets/connect', '/datasets/new/space-1/sources/new'])( + 'should redirect direct external source route to /datasets without dataset.external.connect: %s', + async (pathname) => { + mockPathname = pathname + setConsoleState({ + workspacePermissionKeys: [], + }) - render( - -
datasets
-
, - ) + render( + +
datasets
+
, + ) - expect(screen.queryByText('datasets')).not.toBeInTheDocument() - await waitFor(() => { - expect(mockReplace).toHaveBeenCalledWith('/datasets') - }) - }) + expect(screen.queryByText('datasets')).not.toBeInTheDocument() + await waitFor(() => { + expect(mockReplace).toHaveBeenCalledWith('/datasets') + }) + }, + ) - it('should render direct external dataset connection route when workspace has dataset.external.connect', () => { - mockPathname = '/datasets/connect' - setConsoleState({ - workspacePermissionKeys: ['dataset.external.connect'], - }) + it.each(['/datasets/connect', '/datasets/new/space-1/sources/new'])( + 'should render direct external source route with dataset.external.connect: %s', + (pathname) => { + mockPathname = pathname + setConsoleState({ + workspacePermissionKeys: ['dataset.external.connect'], + }) - render( - -
datasets
-
, - ) + render( + +
datasets
+
, + ) - expect(screen.getByText('datasets')).toBeInTheDocument() - expect(mockReplace).not.toHaveBeenCalled() - }) + expect(screen.getByText('datasets')).toBeInTheDocument() + expect(mockReplace).not.toHaveBeenCalled() + }, + ) it('should disable external knowledge API queries without dataset.external.connect', () => { setConsoleState({ diff --git a/web/app/(commonLayout)/datasets/layout.tsx b/web/app/(commonLayout)/datasets/layout.tsx index b124b04e352..2ec5becd38b 100644 --- a/web/app/(commonLayout)/datasets/layout.tsx +++ b/web/app/(commonLayout)/datasets/layout.tsx @@ -24,7 +24,11 @@ const isDatasetCreatePath = (pathname: string) => { } const isDatasetExternalConnectPath = (pathname: string) => { - return pathname === '/datasets/connect' || pathname.startsWith('/datasets/connect/') + return ( + pathname === '/datasets/connect' || + pathname.startsWith('/datasets/connect/') || + /^\/datasets\/new\/[^/]+\/sources\/new\/?$/.test(pathname) + ) } export default function DatasetsLayout({ children }: { children: React.ReactNode }) { diff --git a/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/new/page.tsx b/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/new/page.tsx new file mode 100644 index 00000000000..a3e3fd4e011 --- /dev/null +++ b/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/new/page.tsx @@ -0,0 +1,7 @@ +import { AddSourcePage } from '@/features/new-rag/add-source-page' + +export default async function Page({ params }: { params: Promise<{ knowledgeSpaceId: string }> }) { + const { knowledgeSpaceId } = await params + + return +} diff --git a/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/page.tsx b/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/page.tsx index a4120ca0eb0..d1ed3327aa8 100644 --- a/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/page.tsx +++ b/web/app/(commonLayout)/datasets/new/[knowledgeSpaceId]/sources/page.tsx @@ -1,5 +1,7 @@ -import { KnowledgeRoutePlaceholder } from '@/features/new-rag/knowledge-route-placeholder' +import { SourcesPage } from '@/features/new-rag/sources-page' -export default function Page() { - return +export default async function Page({ params }: { params: Promise<{ knowledgeSpaceId: string }> }) { + const { knowledgeSpaceId } = await params + + return } diff --git a/web/features/new-rag/__tests__/add-source-page.spec.tsx b/web/features/new-rag/__tests__/add-source-page.spec.tsx new file mode 100644 index 00000000000..c87363c8fe0 --- /dev/null +++ b/web/features/new-rag/__tests__/add-source-page.spec.tsx @@ -0,0 +1,794 @@ +import type { + GetKnowledgeSpacesByIdSourceConnectionsResponse, + GetSourceProvidersResponse, +} from '@dify/contracts/knowledge-fs/types.gen' +import { screen, waitFor } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { render } from '@/test/console/render' +import { AddSourcePage } from '../add-source-page' + +const toastInfoMock = vi.hoisted(() => vi.fn()) + +vi.mock('@langgenius/dify-ui/toast', () => ({ + toast: { info: toastInfoMock }, +})) + +type ConnectionsInfiniteData = { + pages: GetKnowledgeSpacesByIdSourceConnectionsResponse[] +} + +type ConnectionsInfiniteOptions = { + getNextPageParam: ( + lastPage: GetKnowledgeSpacesByIdSourceConnectionsResponse, + ) => string | undefined + input: (pageParam: string | null) => unknown + initialPageParam: string | null +} + +const queryState = vi.hoisted(() => ({ + connections: { + data: { pages: [{ items: [] }] } as ConnectionsInfiniteData | undefined, + error: null as unknown, + fetchNextPage: vi.fn(), + hasNextPage: false, + isFetchNextPageError: false, + isFetchingNextPage: false, + isPending: false, + refetch: vi.fn(), + }, + providers: { + data: undefined as GetSourceProvidersResponse | undefined, + error: null as unknown, + isPending: false, + refetch: vi.fn(), + }, +})) + +const clientMock = vi.hoisted(() => ({ + createConnection: vi.fn(), + deleteConnection: vi.fn(), + refreshConnection: vi.fn(), +})) + +const queryClientMock = vi.hoisted(() => ({ + invalidateQueries: vi.fn(), +})) + +const providerQueryOptionsMock = vi.hoisted(() => vi.fn(() => ({ queryKey: ['source-providers'] }))) +const connectionInfiniteOptionsMock = vi.hoisted(() => + vi.fn((_options: ConnectionsInfiniteOptions) => ({ queryKey: ['source-connections'] })), +) + +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useInfiniteQuery: () => queryState.connections, + useQuery: () => queryState.providers, + useQueryClient: () => queryClientMock, + } +}) + +vi.mock('@/service/client', () => ({ + consoleClient: { + knowledgeFs: { + deleteKnowledgeSpacesByIdSourceConnectionsByConnectionId: clientMock.deleteConnection, + postKnowledgeSpacesByIdSourceConnections: clientMock.createConnection, + postKnowledgeSpacesByIdSourceConnectionsByConnectionIdRefresh: clientMock.refreshConnection, + }, + }, + consoleQuery: { + knowledgeFs: { + getSourceProviders: { + queryOptions: providerQueryOptionsMock, + }, + getKnowledgeSpacesByIdSourceConnections: { + infiniteOptions: connectionInfiniteOptionsMock, + key: vi.fn(() => ['source-connections']), + }, + }, + }, +})) + +const firecrawlProvider: GetSourceProvidersResponse['items'][number] = { + authKinds: ['api-key', 'endpoint'], + available: true, + capabilities: ['website-crawl'], + configuration: [ + { + description: 'Plugin identifier', + name: 'pluginId', + required: true, + secret: false, + type: 'string', + }, + { + description: 'Plugin provider', + name: 'provider', + required: true, + secret: false, + type: 'string', + }, + { + description: 'Plugin datasource', + name: 'datasource', + required: true, + secret: false, + type: 'string', + }, + { + description: 'Firecrawl API key', + format: 'password', + name: 'apiKey', + required: true, + secret: true, + type: 'string', + }, + { + description: 'Generic bearer token', + format: 'password', + name: 'token', + required: false, + secret: true, + type: 'string', + }, + { + description: 'Self-hosted endpoint', + format: 'uri', + name: 'endpoint', + required: false, + secret: false, + type: 'string', + }, + ], + displayName: 'Firecrawl', + id: 'plugin-daemon-website', +} + +const jinaProvider: GetSourceProvidersResponse['items'][number] = { + authKinds: ['api-key'], + available: true, + capabilities: ['website-crawl'], + configuration: [ + { + description: 'Jina API key', + format: 'password', + name: 'apiKey', + required: true, + secret: true, + type: 'string', + }, + ], + displayName: 'Jina Reader', + id: 'jina-reader', +} + +const connection = ( + status: 'provisioning' | 'active' | 'expired' | 'error' | 'revoked', + version = 2, + overrides: Partial = {}, +) => ({ + authKind: 'api-key' as const, + configuration: { + datasource: 'crawl', + pluginId: 'langgenius/firecrawl_datasource', + provider: 'firecrawl', + }, + createdAt: '2026-07-20T10:00:00Z', + id: 'connection-1', + knowledgeSpaceId: 'space-1', + name: 'Firecrawl', + providerId: 'plugin-daemon-website', + scopes: [], + status, + updatedAt: '2026-07-20T10:00:00Z', + version, + ...overrides, +}) + +describe('AddSourcePage', () => { + beforeEach(() => { + vi.clearAllMocks() + clientMock.createConnection.mockReset() + clientMock.deleteConnection.mockReset() + clientMock.refreshConnection.mockReset() + queryState.connections.refetch.mockReset() + queryState.providers.refetch.mockReset() + queryState.providers.data = { items: [firecrawlProvider, jinaProvider] } + queryState.providers.error = null + queryState.providers.isPending = false + queryState.connections.data = { pages: [{ items: [] }] } + queryState.connections.error = null + queryState.connections.hasNextPage = false + queryState.connections.isFetchNextPageError = false + queryState.connections.isFetchingNextPage = false + queryState.connections.isPending = false + }) + + it('loads the provider catalog and every scoped connection cursor page', () => { + queryState.providers.isPending = true + + render() + + expect(providerQueryOptionsMock).toHaveBeenCalledWith({ + context: { silent: true }, + input: {}, + retry: false, + }) + const options = connectionInfiniteOptionsMock.mock.lastCall?.[0] + expect(options).toBeDefined() + if (!options) throw new Error('Expected connection infinite query options') + expect(options.input(null)).toEqual({ params: { id: 'space-1' }, query: { limit: 200 } }) + expect(options.input('next')).toEqual({ + params: { id: 'space-1' }, + query: { cursor: 'next', limit: 200 }, + }) + expect(options.getNextPageParam({ items: [], nextCursor: 'next' })).toBe('next') + expect(options.initialPageParam).toBeNull() + expect(screen.getByRole('status')).toBeInTheDocument() + }) + + it('continues loading connection pages automatically', async () => { + queryState.connections.hasNextPage = true + + render() + + await waitFor(() => expect(queryState.connections.fetchNextPage).toHaveBeenCalledOnce()) + }) + + it('stops automatic connection pagination after a cursor error', () => { + queryState.connections.error = new Error('next page failed') + queryState.connections.hasNextPage = true + queryState.connections.isFetchNextPageError = true + + render() + + expect(queryState.connections.fetchNextPage).not.toHaveBeenCalled() + expect(screen.getByText('dataset.newKnowledge.providerLoadFailed')).toBeInTheDocument() + }) + + it('finds the provider connection on a later loaded page', () => { + queryState.connections.data = { pages: [{ items: [] }, { items: [connection('active')] }] } + + render() + + expect(screen.getByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + expect(screen.getByRole('radio', { name: 'Firecrawl' })).toBeChecked() + expect( + screen.getByText('dataset.newKnowledge.crawlSetupUnavailableDescription'), + ).toBeInTheDocument() + expect(screen.queryByRole('textbox')).not.toBeInTheDocument() + expect( + screen.queryByRole('button', { name: 'dataset.newKnowledge.crawlAndPreview' }), + ).not.toBeInTheDocument() + }) + + it('creates the exact Firecrawl provider connection without leaking credentials', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockResolvedValue(connection('active')) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'secret-value') + expect(screen.getByLabelText('Token')).toBeInTheDocument() + expect(screen.getByLabelText('Endpoint')).toBeInTheDocument() + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + await waitFor(() => + expect(clientMock.createConnection).toHaveBeenCalledWith({ + body: { + authKind: 'api-key', + configuration: { + datasource: 'crawl', + pluginId: 'langgenius/firecrawl_datasource', + provider: 'firecrawl', + }, + credentials: { apiKey: 'secret-value' }, + name: 'Firecrawl', + providerId: 'plugin-daemon-website', + }, + params: { id: 'space-1' }, + }), + ) + expect(queryClientMock.invalidateQueries).toHaveBeenCalledWith({ + queryKey: ['source-connections'], + }) + expect(screen.getByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + expect(screen.queryByDisplayValue('secret-value')).not.toBeInTheDocument() + }) + + it('renders the provider catalog returned by the API without invented entries', () => { + queryState.providers.data = { + items: [{ ...jinaProvider, displayName: 'Workspace Reader' }], + } + + render() + + expect(screen.getByRole('radio', { name: 'Workspace Reader' })).toBeChecked() + expect(screen.queryByRole('radio', { name: 'Firecrawl' })).not.toBeInTheDocument() + expect(screen.queryByRole('radio', { name: 'WaterCrawl' })).not.toBeInTheDocument() + }) + + it('keeps every installed provider selectable when the preferred provider is returned later', () => { + queryState.providers.data = { + items: [ + ...Array.from({ length: 4 }, (_, index) => ({ + ...jinaProvider, + displayName: `Provider ${index + 1}`, + id: `provider-${index + 1}`, + })), + firecrawlProvider, + ], + } + + render() + + expect(screen.getByRole('radio', { name: 'Provider 4' })).toBeInTheDocument() + expect(screen.getByRole('radio', { name: 'Firecrawl' })).toBeChecked() + }) + + it('switches providers and creates a connection from the selected catalog schema', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockResolvedValue( + connection('active', 1, { + id: 'jina-connection', + name: 'Jina Reader', + providerId: 'jina-reader', + }), + ) + + render() + await user.click(screen.getByRole('radio', { name: 'Jina Reader' })) + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'jina-secret') + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + await waitFor(() => + expect(clientMock.createConnection).toHaveBeenCalledWith({ + body: { + authKind: 'api-key', + configuration: {}, + credentials: { apiKey: 'jina-secret' }, + name: 'Jina Reader', + providerId: 'jina-reader', + }, + params: { id: 'space-1' }, + }), + ) + }) + + it('clears the configuration form when the selected provider changes', async () => { + const user = userEvent.setup() + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'firecrawl-secret') + await user.click(screen.getByRole('radio', { name: 'Jina Reader' })) + + expect( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ).toBeInTheDocument() + expect(screen.queryByDisplayValue('firecrawl-secret')).not.toBeInTheDocument() + }) + + it('clears sensitive input but retains non-sensitive input after a connection error', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockRejectedValue(new Error('provider unavailable')) + queryState.connections.refetch.mockResolvedValue({ data: queryState.connections.data }) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'do-not-retain') + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.authKind.endpoint' })) + await user.type(screen.getByLabelText('Endpoint'), 'https://crawl.example.com') + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + expect(await screen.findByText(/dataset\.newKnowledge\.connectionFailed/)).toBeInTheDocument() + expect(screen.getByLabelText('Endpoint')).toHaveValue('https://crawl.example.com') + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.authKind.api-key' })) + expect(screen.getByLabelText(/Api Key/)).toHaveValue('') + }) + + it('reconciles a response-lost create before showing an error', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockRejectedValue(new Error('response lost')) + queryState.connections.refetch.mockResolvedValue({ + data: { pages: [{ items: [connection('active')] }] }, + }) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'secret-value') + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + expect(await screen.findByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + expect(screen.queryByText(/dataset\.newKnowledge\.connectionFailed/)).not.toBeInTheDocument() + }) + + it('retries response-lost create reconciliation while the connection replica catches up', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockRejectedValue(new Error('response lost')) + queryState.connections.refetch + .mockResolvedValueOnce({ data: { pages: [{ items: [] }] } }) + .mockResolvedValueOnce({ data: { pages: [{ items: [connection('active')] }] } }) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'secret-value') + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + expect(await screen.findByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + expect(queryState.connections.refetch).toHaveBeenCalledTimes(2) + expect(screen.queryByText(/dataset\.newKnowledge\.connectionFailed/)).not.toBeInTheDocument() + }) + + it('clears an API key when authentication modes are changed and changed back', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockResolvedValue(connection('active')) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'must-not-return') + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.authKind.endpoint' })) + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.authKind.api-key' })) + + expect(screen.getByLabelText(/Api Key/)).toHaveValue('') + }) + + it('supports an endpoint descriptor without sending a hidden secret field', async () => { + const user = userEvent.setup() + clientMock.createConnection.mockResolvedValue({ ...connection('active'), authKind: 'endpoint' }) + queryState.providers.data = { + items: [ + { + ...firecrawlProvider, + configuration: [ + ...firecrawlProvider.configuration, + { + description: 'Deployment region', + name: 'region', + required: true, + secret: false, + type: 'string', + }, + ], + }, + ], + } + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + await user.type(screen.getByLabelText(/Api Key/), 'must-not-be-sent') + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.authKind.endpoint' })) + await user.type(screen.getByLabelText('Endpoint'), 'https://crawl.example.com') + await user.type(screen.getByLabelText(/Region/), 'us-east-1') + await user.click(screen.getByRole('button', { name: /dataset\.newKnowledge\.connectProvider/ })) + + await waitFor(() => + expect(clientMock.createConnection).toHaveBeenCalledWith({ + body: { + authKind: 'endpoint', + configuration: { + datasource: 'crawl', + endpoint: 'https://crawl.example.com', + pluginId: 'langgenius/firecrawl_datasource', + provider: 'firecrawl', + region: 'us-east-1', + }, + credentials: {}, + name: 'Firecrawl', + providerId: 'plugin-daemon-website', + }, + params: { id: 'space-1' }, + }), + ) + }) + + it('associates provider field descriptions with their controls', async () => { + const user = userEvent.setup() + const booleanProvider = { + ...firecrawlProvider, + configuration: [ + ...firecrawlProvider.configuration, + { + description: 'Use stealth mode', + name: 'stealth', + required: false, + secret: false, + type: 'boolean' as const, + }, + ], + } + queryState.providers.data = { items: [booleanProvider] } + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + + expect(screen.getByLabelText(/Api Key/)).toHaveAccessibleDescription('Firecrawl API key') + expect(screen.getByLabelText('Stealth')).toHaveAccessibleDescription('Use stealth mode') + }) + + it('refreshes an errored connection using its current version', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('error')] }] } + clientMock.refreshConnection.mockResolvedValue(connection('active')) + + render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + + await waitFor(() => + expect(clientMock.refreshConnection).toHaveBeenCalledWith({ + body: { expectedVersion: 2 }, + params: { connectionId: 'connection-1', id: 'space-1' }, + }), + ) + expect(queryClientMock.invalidateQueries).toHaveBeenCalled() + expect(screen.getByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + }) + + it('revokes an invalid connection before offering a clean reconfiguration form', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('expired')] }] } + clientMock.deleteConnection.mockResolvedValue(connection('revoked', 3)) + + render() + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + + await waitFor(() => + expect(clientMock.deleteConnection).toHaveBeenCalledWith({ + params: { connectionId: 'connection-1', id: 'space-1' }, + query: { expectedVersion: 2 }, + }), + ) + await user.click( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ) + expect(screen.getByLabelText(/Api Key/)).toHaveValue('') + }) + + it('treats a revoked connection as available for clean configuration', () => { + queryState.connections.data = { pages: [{ items: [connection('revoked')] }] } + + render() + + expect( + screen.getByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ).toBeInTheDocument() + expect(screen.queryByRole('button', { name: 'common.operation.retry' })).not.toBeInTheDocument() + }) + + it('reconciles a refresh version race and retries with the server version', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('error')] }] } + clientMock.refreshConnection + .mockRejectedValueOnce(new Error('version conflict')) + .mockResolvedValueOnce(connection('active', 4)) + queryState.connections.refetch.mockResolvedValue({ + data: { + pages: [ + { + items: [ + connection('error', 3), + { + ...connection('error', 8), + id: 'connection-2', + updatedAt: '2026-07-20T11:00:00Z', + }, + ], + }, + ], + }, + }) + + render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + await waitFor(() => expect(queryState.connections.refetch).toHaveBeenCalledOnce()) + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + + await waitFor(() => + expect(clientMock.refreshConnection).toHaveBeenLastCalledWith({ + body: { expectedVersion: 3 }, + params: { connectionId: 'connection-1', id: 'space-1' }, + }), + ) + }) + + it('does not regress the current version when reconciliation reads a stale replica', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('error', 3)] }] } + clientMock.refreshConnection + .mockRejectedValueOnce(new Error('response lost')) + .mockResolvedValueOnce(connection('active', 4)) + queryState.connections.refetch.mockResolvedValue({ + data: { pages: [{ items: [connection('error', 2)] }] }, + }) + + render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + await waitFor(() => expect(queryState.connections.refetch).toHaveBeenCalledOnce()) + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + + await waitFor(() => + expect(clientMock.refreshConnection).toHaveBeenLastCalledWith({ + body: { expectedVersion: 3 }, + params: { connectionId: 'connection-1', id: 'space-1' }, + }), + ) + }) + + it('lets a newer remote connection version replace a local mutation response', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('error')] }] } + clientMock.refreshConnection.mockResolvedValue(connection('provisioning', 3)) + + const view = render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + expect( + await screen.findByText(/dataset\.newKnowledge\.connectionProvisioning/), + ).toBeInTheDocument() + + queryState.connections.data = { + pages: [ + { + items: [ + connection('active', 3), + { + ...connection('active', 10), + id: 'connection-2', + updatedAt: '2026-07-20T11:00:00Z', + }, + ], + }, + ], + } + view.rerender() + + expect(screen.getByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + }) + + it('reconciles a provisioning connection with the refreshed server state', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('provisioning')] }] } + queryState.connections.refetch.mockResolvedValue({ + data: { pages: [{ items: [connection('active')] }] }, + }) + + render() + await user.click( + screen.getByRole('button', { name: 'dataset.newKnowledge.refreshConnectionStatus' }), + ) + + expect(await screen.findByText(/dataset\.newKnowledge\.providerConnected/)).toBeInTheDocument() + }) + + it('shows a retryable error when provisioning reconciliation fails', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('provisioning')] }] } + queryState.connections.refetch.mockResolvedValue({ + data: queryState.connections.data, + error: new Error('temporary failure'), + }) + + render() + await user.click( + screen.getByRole('button', { name: 'dataset.newKnowledge.refreshConnectionStatus' }), + ) + + expect(await screen.findByRole('alert')).toHaveTextContent( + 'dataset.newKnowledge.connectionRefreshFailed', + ) + }) + + it('shows a retryable error when provisioning reconciliation finds no connection', async () => { + const user = userEvent.setup() + queryState.connections.data = { pages: [{ items: [connection('provisioning')] }] } + queryState.connections.refetch.mockImplementation(async () => { + queryState.connections.data = { pages: [{ items: [] }] } + return { data: queryState.connections.data } + }) + + const view = render() + await user.click( + screen.getByRole('button', { name: 'dataset.newKnowledge.refreshConnectionStatus' }), + ) + view.rerender() + + expect(await screen.findByRole('alert')).toHaveTextContent( + 'dataset.newKnowledge.connectionRefreshFailed', + ) + expect( + screen.queryByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ).not.toBeInTheDocument() + }) + + it('keeps source types selectable and shows an honest dependency state', async () => { + const user = userEvent.setup() + render() + + expect(screen.getByRole('radio', { name: 'dataset.newKnowledge.websiteCrawl' })).toBeChecked() + const onlineDocuments = screen.getByRole('radio', { + name: 'dataset.newKnowledge.onlineDocuments', + }) + expect(onlineDocuments).toBeEnabled() + expect(screen.getByRole('radio', { name: 'dataset.newKnowledge.onlineDrive' })).toBeEnabled() + expect( + screen.getByRole('group', { name: 'dataset.newKnowledge.providerLabel' }), + ).toBeInTheDocument() + expect(screen.getByRole('radio', { name: 'Firecrawl' })).toBeChecked() + expect(screen.getByRole('radio', { name: 'Jina Reader' })).toBeEnabled() + expect(screen.queryByRole('radio', { name: 'WaterCrawl' })).not.toBeInTheDocument() + expect(screen.queryByRole('radio', { name: 'FakeCrawler' })).not.toBeInTheDocument() + expect( + screen.getByRole('link', { name: 'dataset.newKnowledge.moreProviders' }), + ).toHaveAttribute('href', '/marketplace?category=datasource') + + await user.click(onlineDocuments) + expect(onlineDocuments).toBeChecked() + expect( + screen.queryByRole('group', { name: 'datasetCreation.stepOne.website.chooseProvider' }), + ).not.toBeInTheDocument() + expect(screen.getByRole('status')).toHaveTextContent('dataset.newKnowledge.providerUnavailable') + }) + + it('keeps the final Add source action disabled until a crawl result is ready', async () => { + const user = userEvent.setup() + render() + + await user.click(screen.getByRole('radio', { name: 'dataset.newKnowledge.onlineDocuments' })) + const addSource = screen.getByRole('button', { name: 'dataset.newKnowledge.addSource' }) + expect(addSource).toBeDisabled() + expect(toastInfoMock).not.toHaveBeenCalled() + }) + + it('shows catalog unavailability instead of offering a fake connection', () => { + queryState.providers.data = { + items: [{ ...firecrawlProvider, available: false, unavailableReason: 'Disabled by admin' }], + } + + render() + + expect(screen.getByText('Disabled by admin')).toBeInTheDocument() + expect( + screen.queryByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ).not.toBeInTheDocument() + }) + + it('does not offer unsupported OAuth or undocumented direct connection paths', () => { + queryState.providers.data = { + items: [ + { + ...firecrawlProvider, + authKinds: ['oauth2'], + configuration: firecrawlProvider.configuration.slice(0, 3), + }, + ], + } + + render() + + expect(screen.getByText('dataset.newKnowledge.providerUnavailable')).toBeInTheDocument() + expect( + screen.queryByRole('button', { name: /dataset\.newKnowledge\.configureProvider/ }), + ).not.toBeInTheDocument() + }) +}) diff --git a/web/features/new-rag/__tests__/sources-page.spec.tsx b/web/features/new-rag/__tests__/sources-page.spec.tsx new file mode 100644 index 00000000000..ea67db85648 --- /dev/null +++ b/web/features/new-rag/__tests__/sources-page.spec.tsx @@ -0,0 +1,655 @@ +import type { Source } from '@dify/contracts/knowledge-fs/types.gen' +import { screen, waitFor, within } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import datasetTranslations from '@/i18n/en-US/dataset.json' +import { render } from '@/test/console/render' +import { SourcesPage } from '../sources-page' + +const toastInfoMock = vi.hoisted(() => vi.fn()) +const toastErrorMock = vi.hoisted(() => vi.fn()) +const permissionState = vi.hoisted(() => ({ + workspacePermissionKeys: ['dataset.acl.edit', 'dataset.external.connect'], +})) + +vi.mock('@langgenius/dify-ui/toast', () => ({ + toast: { error: toastErrorMock, info: toastInfoMock }, +})) + +vi.mock('@/context/permission-state', async () => { + const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture') + + return createPermissionStateModuleMock(() => permissionState) +}) + +type SourcesInfiniteOptions = { + getNextPageParam: (lastPage: { nextCursor?: string }) => string | undefined + input: (pageParam: string | null) => unknown + initialPageParam: string | null + refetchInterval: (query: { + state: { + data?: { pages: Array<{ items: Source[] }> } + } + }) => false | number +} + +const sourcesQuery = vi.hoisted(() => ({ + data: undefined as { pages: Array<{ items: Source[]; nextCursor?: string }> } | undefined, + error: null as unknown, + fetchNextPage: vi.fn(), + hasNextPage: false, + isFetchNextPageError: false, + isFetchingNextPage: false, + isPending: false, + refetch: vi.fn(), +})) + +const infiniteOptionsMock = vi.hoisted(() => vi.fn((_options: SourcesInfiniteOptions) => ({}))) +const clientMock = vi.hoisted(() => ({ + deleteSource: vi.fn(), + patchSource: vi.fn(), + syncSource: vi.fn(), +})) +const invalidateQueriesMock = vi.hoisted(() => vi.fn()) + +vi.mock('@tanstack/react-query', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + useInfiniteQuery: () => sourcesQuery, + useQueryClient: () => ({ invalidateQueries: invalidateQueriesMock }), + } +}) + +vi.mock('@/service/client', () => ({ + consoleClient: { + knowledgeFs: { + deleteKnowledgeSpacesByIdSourcesBySourceId: clientMock.deleteSource, + patchKnowledgeSpacesByIdSourcesBySourceId: clientMock.patchSource, + postKnowledgeSpacesByIdSourcesBySourceIdSync: clientMock.syncSource, + }, + }, + consoleQuery: { + knowledgeFs: { + getKnowledgeSpacesByIdSources: { + infiniteOptions: infiniteOptionsMock, + key: vi.fn(() => ['sources']), + }, + }, + }, +})) + +const source = (overrides: Partial): Source => ({ + createdAt: '2026-07-20T10:00:00Z', + id: 'source-1', + knowledgeSpaceId: 'space-1', + metadata: {}, + name: 'Product documentation', + status: 'active', + type: 'web', + updatedAt: '2026-07-20T10:00:00Z', + uri: 'https://docs.example.com', + version: 3, + ...overrides, +}) + +describe('SourcesPage', () => { + beforeEach(() => { + vi.clearAllMocks() + sourcesQuery.data = undefined + sourcesQuery.error = null + sourcesQuery.hasNextPage = false + sourcesQuery.isFetchNextPageError = false + sourcesQuery.isFetchingNextPage = false + sourcesQuery.isPending = false + clientMock.deleteSource.mockResolvedValue({ status: 'accepted' }) + clientMock.patchSource.mockResolvedValue(source({})) + clientMock.syncSource.mockResolvedValue({ state: 'queued' }) + permissionState.workspacePermissionKeys = ['dataset.acl.edit', 'dataset.external.connect'] + }) + + it('loads sources through the KnowledgeFS contract', () => { + sourcesQuery.isPending = true + + render() + + const options = infiniteOptionsMock.mock.lastCall?.[0] + expect(options).toBeDefined() + if (!options) throw new Error('Expected source infinite query options') + expect(options.input(null)).toEqual({ + params: { id: 'space-1' }, + query: { limit: 50 }, + }) + expect(options.input('next')).toEqual({ + params: { id: 'space-1' }, + query: { cursor: 'next', limit: 50 }, + }) + expect(options.getNextPageParam({ nextCursor: 'next' })).toBe('next') + expect(options.initialPageParam).toBeNull() + expect( + options.refetchInterval({ + state: { data: { pages: [{ items: [source({ status: 'syncing' })] }] } }, + }), + ).toBe(3000) + expect( + options.refetchInterval({ + state: { data: { pages: [{ items: [source({ status: 'active' })] }] } }, + }), + ).toBe(false) + expect(screen.getByRole('status')).toBeInTheDocument() + }) + + it('renders the designed empty state and enters the real add-source route', () => { + sourcesQuery.data = { pages: [{ items: [] }] } + + const { container } = render() + + expect(screen.getByText('dataset.newKnowledge.sourcesEmptyTitle')).toBeInTheDocument() + expect(datasetTranslations['newKnowledge.sourcesEmptyDescription']).toBe( + 'Connect a website, workspace, or drive — Dify keeps it synced and fresh, so retrieval never breaks.', + ) + expect( + screen.getByRole('heading', { name: 'dataset.newKnowledge.sources' }), + ).toBeInTheDocument() + expect(screen.getByRole('link', { name: 'dataset.newKnowledge.addSource' })).toHaveAttribute( + 'href', + '/datasets/new/space-1/sources/new', + ) + for (const brand of ['firecrawl', 'jina', 'notion', 'google-drive', 'confluence', 'more']) + expect(container.querySelector(`[data-brand="${brand}"]`)).toBeInTheDocument() + expect(container.querySelector('[data-brand="firecrawl"]')?.tagName).toBe('SPAN') + expect(container.querySelector('[data-brand="firecrawl"]')).toHaveClass('size-8') + expect(container.querySelector('[data-brand="jina"]')).toHaveClass('i-custom-public-llm-jina') + expect(container.querySelector('[data-brand="confluence"]')).toHaveClass( + 'i-custom-public-common-confluence', + ) + }) + + it('renders real source statuses and filters by status and search text', async () => { + const user = userEvent.setup() + sourcesQuery.data = { + pages: [ + { + items: [ + source({ id: 'active', name: 'Product documentation', status: 'active' }), + source({ id: 'syncing', name: 'API reference', status: 'syncing' }), + source({ id: 'disabled', name: 'Legacy FAQ', status: 'disabled' }), + source({ id: 'error', name: 'Support site', status: 'error' }), + ], + }, + ], + } + + render() + + expect(screen.getAllByText('dataset.newKnowledge.sourceStatus.active')).toHaveLength(2) + expect(screen.getAllByText('dataset.newKnowledge.sourceStatus.syncing')).toHaveLength(2) + expect(screen.getAllByText('dataset.newKnowledge.sourceStatus.disabled')).toHaveLength(2) + expect(screen.getAllByText('dataset.newKnowledge.sourceStatus.error')).toHaveLength(2) + + await user.selectOptions( + screen.getByRole('combobox', { name: 'dataset.newKnowledge.sourceFilterLabel' }), + 'error', + ) + expect(screen.getByText('Support site')).toBeInTheDocument() + expect(screen.queryByText('Product documentation')).not.toBeInTheDocument() + + await user.selectOptions( + screen.getByRole('combobox', { name: 'dataset.newKnowledge.sourceFilterLabel' }), + 'all', + ) + await user.type( + screen.getByRole('searchbox', { name: 'dataset.newKnowledge.searchSources' }), + 'api', + ) + expect(screen.getByText('API reference')).toBeInTheDocument() + expect(screen.queryByText('Support site')).not.toBeInTheDocument() + }) + + it('sorts loaded sources by name from the source column header', async () => { + const user = userEvent.setup() + sourcesQuery.data = { + pages: [ + { + items: [ + source({ id: 'zulu', name: 'Zulu docs' }), + source({ id: 'alpha', name: 'Alpha docs' }), + ], + }, + ], + } + + render() + + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.sourceColumn' })) + const rowsAscending = screen.getAllByRole('row').slice(1) + expect(within(rowsAscending[0]!).getByText('Alpha docs')).toBeInTheDocument() + expect(within(rowsAscending[1]!).getByText('Zulu docs')).toBeInTheDocument() + + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.sourceColumn' })) + const rowsDescending = screen.getAllByRole('row').slice(1) + expect(within(rowsDescending[0]!).getByText('Zulu docs')).toBeInTheDocument() + expect(within(rowsDescending[1]!).getByText('Alpha docs')).toBeInTheDocument() + }) + + it('opens a source URI from the row action menu', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})] }] } + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + + const openSource = screen.getByRole('menuitem', { name: 'common.operation.openInNewTab' }) + expect(openSource).toHaveAttribute('href', 'https://docs.example.com') + expect(openSource).toHaveAttribute('target', '_blank') + expect(openSource).toHaveAttribute('rel', 'noopener noreferrer') + }) + + it('hides the row action menu when a read-only source has no openable URI', () => { + permissionState.workspacePermissionKeys = ['dataset.acl.readonly'] + sourcesQuery.data = { + pages: [ + { + items: [ + source({ + type: 'object-storage', + uri: 's3://private-bucket/product-documentation', + }), + ], + }, + ], + } + + render() + + expect( + screen.queryByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ).not.toBeInTheDocument() + }) + + it('uses dataset.external.connect for every source mutation action', async () => { + const user = userEvent.setup() + permissionState.workspacePermissionKeys = ['dataset.external.connect'] + sourcesQuery.data = { pages: [{ items: [source({})] }] } + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + + expect( + screen.getByRole('menuitem', { name: 'dataset.newKnowledge.syncNow' }), + ).toBeInTheDocument() + expect( + screen.getByRole('menuitem', { name: 'dataset.newKnowledge.disableSource' }), + ).toBeInTheDocument() + expect( + screen.getByRole('menuitem', { name: 'dataset.newKnowledge.removeSource' }), + ).toBeInTheDocument() + }) + + it('hides source mutations without dataset.external.connect', async () => { + const user = userEvent.setup() + permissionState.workspacePermissionKeys = ['dataset.acl.edit', 'dataset.create_and_management'] + sourcesQuery.data = { pages: [{ items: [source({})] }] } + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + + expect( + screen.getByRole('menuitem', { name: 'common.operation.openInNewTab' }), + ).toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.syncNow' }), + ).not.toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.disableSource' }), + ).not.toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.removeSource' }), + ).not.toBeInTheDocument() + }) + + it('syncs a source through the real KnowledgeFS action', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})] }] } + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + + await user.click(screen.getByRole('menuitem', { name: 'dataset.newKnowledge.syncNow' })) + + await waitFor(() => + expect(clientMock.syncSource).toHaveBeenCalledWith({ + headers: { 'Idempotency-Key': expect.any(String) }, + params: { id: 'space-1', sourceId: 'source-1' }, + }), + ) + expect( + within(screen.getByRole('row', { name: /Product documentation/ })).getByText( + 'dataset.newKnowledge.sourceStatus.syncing', + ), + ).toBeInTheDocument() + const options = infiniteOptionsMock.mock.lastCall?.[0] + expect(options).toBeDefined() + if (!options) throw new Error('Expected source infinite query options') + expect( + options.refetchInterval({ + state: { data: { pages: [{ items: [source({ status: 'active' })] }] } }, + }), + ).toBe(3000) + expect(invalidateQueriesMock).toHaveBeenCalledWith({ queryKey: ['sources'] }) + }) + + it('disables and re-enables a source through the real patch endpoint', async () => { + const user = userEvent.setup() + sourcesQuery.data = { + pages: [ + { + items: [source({ id: 'active-source' }), source({ id: 'disabled', status: 'disabled' })], + }, + ], + } + + render() + const actionButtons = screen.getAllByRole('button', { + name: /dataset.newKnowledge.sourceActions/, + }) + const activeSourceActions = actionButtons[0] + const disabledSourceActions = actionButtons[1] + if (!activeSourceActions || !disabledSourceActions) + throw new Error('Expected actions for both sources') + await user.click(activeSourceActions) + await user.click(screen.getByRole('menuitem', { name: 'dataset.newKnowledge.disableSource' })) + await waitFor(() => + expect(clientMock.patchSource).toHaveBeenCalledWith({ + body: { expectedVersion: 3, status: 'disabled' }, + params: { id: 'space-1', sourceId: 'active-source' }, + }), + ) + + await user.click(disabledSourceActions) + await user.click(screen.getByRole('menuitem', { name: 'dataset.enable' })) + await waitFor(() => + expect(clientMock.patchSource).toHaveBeenLastCalledWith({ + body: { expectedVersion: 3, status: 'active' }, + params: { id: 'space-1', sourceId: 'disabled' }, + }), + ) + }) + + it('uses the returned source version while the list replica is stale', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})] }] } + clientMock.patchSource + .mockResolvedValueOnce( + source({ + status: 'disabled', + updatedAt: '2026-07-20T10:01:00Z', + version: 4, + }), + ) + .mockResolvedValueOnce( + source({ + status: 'active', + updatedAt: '2026-07-20T10:02:00Z', + version: 5, + }), + ) + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + await user.click(screen.getByRole('menuitem', { name: 'dataset.newKnowledge.disableSource' })) + + expect( + within(screen.getByRole('row', { name: /Product documentation/ })).getByText( + 'dataset.newKnowledge.sourceStatus.disabled', + ), + ).toBeInTheDocument() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + await user.click(screen.getByRole('menuitem', { name: 'dataset.enable' })) + + await waitFor(() => + expect(clientMock.patchSource).toHaveBeenLastCalledWith({ + body: { expectedVersion: 4, status: 'active' }, + params: { id: 'space-1', sourceId: 'source-1' }, + }), + ) + }) + + it('requires confirmation before removing a source', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})] }] } + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + await user.click(screen.getByRole('menuitem', { name: 'dataset.newKnowledge.removeSource' })) + + expect(clientMock.deleteSource).not.toHaveBeenCalled() + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.removeSource' })) + await waitFor(() => + expect(clientMock.deleteSource).toHaveBeenCalledWith({ + body: { expectedRevision: 3 }, + headers: { 'idempotency-key': expect.any(String) }, + params: { id: 'space-1', sourceId: 'source-1' }, + query: { documents: 'keep' }, + }), + ) + expect(screen.queryByText('Product documentation')).not.toBeInTheDocument() + }) + + it('keeps the removal confirmation open when the request fails', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})] }] } + clientMock.deleteSource.mockRejectedValue(new Error('temporary failure')) + + render() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + await user.click(screen.getByRole('menuitem', { name: 'dataset.newKnowledge.removeSource' })) + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.removeSource' })) + + await waitFor(() => + expect(toastErrorMock).toHaveBeenCalledWith('dataset.newKnowledge.sourcesErrorDescription'), + ) + expect( + screen.getByRole('button', { name: 'dataset.newKnowledge.removeSource' }), + ).toBeInTheDocument() + expect(invalidateQueriesMock).toHaveBeenCalledWith({ queryKey: ['sources'] }) + }) + + it('retries an errored source and shows its queued state', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({ status: 'error' })] }] } + + render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + + await waitFor(() => expect(clientMock.syncSource).toHaveBeenCalledOnce()) + expect( + within(screen.getByRole('row', { name: /Product documentation/ })).getByText( + 'dataset.newKnowledge.sourceStatus.syncing', + ), + ).toBeInTheDocument() + }) + + it('supports row selection and a true indeterminate select-all state', async () => { + const user = userEvent.setup() + sourcesQuery.data = { + pages: [{ items: [source({ id: 'first' }), source({ id: 'second' })] }], + } + + render() + const checkboxes = screen.getAllByRole('checkbox') + expect(checkboxes).toHaveLength(3) + const selectAll = checkboxes[0] + const firstSource = checkboxes[1] + const secondSource = checkboxes[2] + if (!selectAll || !firstSource || !secondSource) throw new Error('Expected source checkboxes') + await user.click(firstSource) + expect(selectAll).toHaveAttribute('data-indeterminate') + + await user.click(selectAll) + expect(firstSource).toBeChecked() + expect(secondSource).toBeChecked() + }) + + it('offers a real retry when the source list cannot load', async () => { + const user = userEvent.setup() + sourcesQuery.error = new Error('temporary failure') + + render() + await user.click(screen.getByRole('button', { name: 'common.operation.retry' })) + + expect(sourcesQuery.refetch).toHaveBeenCalledOnce() + }) + + it('loads the next real cursor page on demand', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})], nextCursor: 'next' }] } + sourcesQuery.hasNextPage = true + + render() + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.loadMore' })) + + expect(sourcesQuery.fetchNextPage).toHaveBeenCalledOnce() + }) + + it('continues from an empty cursor page when a later page exists', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [], nextCursor: 'next' }] } + sourcesQuery.hasNextPage = true + + render() + + expect(screen.queryByText('dataset.newKnowledge.sourcesEmptyTitle')).not.toBeInTheDocument() + await user.click(screen.getByRole('button', { name: 'dataset.newKnowledge.loadMore' })) + expect(sourcesQuery.fetchNextPage).toHaveBeenCalledOnce() + }) + + it('continues through cursor pages before declaring a filtered search empty', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})], nextCursor: 'next' }] } + sourcesQuery.hasNextPage = true + + render() + await user.type( + screen.getByRole('searchbox', { name: 'dataset.newKnowledge.searchSources' }), + 'later page', + ) + + expect(sourcesQuery.fetchNextPage).toHaveBeenCalledOnce() + expect(screen.queryByText('dataset.newKnowledge.noMatchingSources')).not.toBeInTheDocument() + }) + + it('caps automatic filtered pagination and offers explicit continuation', async () => { + const user = userEvent.setup() + sourcesQuery.data = { + pages: Array.from({ length: 4 }, (_, index) => ({ + items: [source({ id: `source-${index}`, name: `Source ${index}` })], + nextCursor: `cursor-${index + 1}`, + })), + } + sourcesQuery.hasNextPage = true + + render() + await user.type( + screen.getByRole('searchbox', { name: 'dataset.newKnowledge.searchSources' }), + 'later page', + ) + + expect(sourcesQuery.fetchNextPage).not.toHaveBeenCalled() + expect( + screen.getByRole('button', { name: 'dataset.newKnowledge.loadMore' }), + ).toBeInTheDocument() + }) + + it('stops automatic filtered pagination after a cursor error', async () => { + const user = userEvent.setup() + sourcesQuery.data = { pages: [{ items: [source({})], nextCursor: 'next' }] } + sourcesQuery.hasNextPage = true + sourcesQuery.isFetchNextPageError = true + + render() + await user.type( + screen.getByRole('searchbox', { name: 'dataset.newKnowledge.searchSources' }), + 'later page', + ) + + expect(sourcesQuery.fetchNextPage).not.toHaveBeenCalled() + expect(screen.getByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('status')).not.toBeInTheDocument() + expect(screen.queryByText('dataset.newKnowledge.noMatchingSources')).not.toBeInTheDocument() + }) + + it('shows provider and source type as separate row details', () => { + sourcesQuery.data = { + pages: [{ items: [source({ metadata: { providerName: 'Firecrawl' } })] }], + } + + render() + + expect(screen.getByText('Firecrawl')).toBeInTheDocument() + expect(screen.getByText('dataset.newKnowledge.sourceType.web')).toBeInTheDocument() + }) + + it('keeps read-only source viewing while hiding mutation and add-source actions', async () => { + const user = userEvent.setup() + permissionState.workspacePermissionKeys = ['dataset.acl.readonly'] + sourcesQuery.data = { pages: [{ items: [source({ status: 'error' })] }] } + + render() + + expect( + screen.queryByRole('link', { name: 'dataset.newKnowledge.addSource' }), + ).not.toBeInTheDocument() + expect(screen.queryByRole('button', { name: 'common.operation.retry' })).not.toBeInTheDocument() + await user.click( + screen.getByRole('button', { + name: 'dataset.newKnowledge.sourceActions:{"name":"Product documentation"}', + }), + ) + expect( + screen.getByRole('menuitem', { name: 'common.operation.openInNewTab' }), + ).toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.syncNow' }), + ).not.toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.disableSource' }), + ).not.toBeInTheDocument() + expect( + screen.queryByRole('menuitem', { name: 'dataset.newKnowledge.removeSource' }), + ).not.toBeInTheDocument() + }) +}) diff --git a/web/features/new-rag/add-source-page.tsx b/web/features/new-rag/add-source-page.tsx new file mode 100644 index 00000000000..2f0cf53b43d --- /dev/null +++ b/web/features/new-rag/add-source-page.tsx @@ -0,0 +1,898 @@ +'use client' + +import type { + GetKnowledgeSpacesByIdSourceConnectionsResponse, + GetSourceProvidersResponse, +} from '@dify/contracts/knowledge-fs/types.gen' +import { Button } from '@langgenius/dify-ui/button' +import { cn } from '@langgenius/dify-ui/cn' +import { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query' +import { useCallback, useEffect, useId, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Loading from '@/app/components/base/loading' +import Link from '@/next/link' +import { consoleClient, consoleQuery } from '@/service/client' +import { newKnowledgeDetailPath } from './routes' + +type Provider = GetSourceProvidersResponse['items'][number] +type ProviderField = Provider['configuration'][number] +type Connection = GetKnowledgeSpacesByIdSourceConnectionsResponse['items'][number] +type ConnectionAuthKind = 'api-key' | 'endpoint' +type SourceType = 'onlineDocuments' | 'onlineDrive' | 'websiteCrawl' + +const CONNECTION_PAGE_SIZE = 200 +const CONNECTION_RECONCILIATION_RETRY_DELAYS = [0, 100, 300] +const FIRECRAWL_PROVIDER_ID = 'plugin-daemon-website' +const FIRECRAWL_CONFIGURATION = { + datasource: 'crawl', + pluginId: 'langgenius/firecrawl_datasource', + provider: 'firecrawl', +} as const +const FIRECRAWL_FIXED_FIELD_NAMES = new Set(Object.keys(FIRECRAWL_CONFIGURATION)) +const CONNECTION_STATUS_PRIORITY: Record = { + active: 0, + provisioning: 1, + error: 2, + expired: 3, + revoked: 4, +} + +function humanizeFieldName(name: string) { + return name + .replace(/([a-z0-9])([A-Z])/g, '$1 $2') + .replace(/[-_]+/g, ' ') + .replace(/^./, (character) => character.toUpperCase()) +} + +function fieldValue(value: string, type: ProviderField['type']) { + if (type === 'boolean') return value === 'true' + if (type === 'integer') return Number.parseInt(value, 10) + return value.trim() +} + +function providerIconClass(provider: Provider) { + const identity = `${provider.id} ${provider.displayName}`.toLocaleLowerCase() + if (provider.id === FIRECRAWL_PROVIDER_ID || identity.includes('firecrawl')) + return 'i-ri-fire-fill text-orange-500' + if (identity.includes('jina')) return 'i-custom-public-llm-jina' + if (identity.includes('water')) return 'i-ri-water-flash-line text-util-colors-blue-blue-600' + return 'i-ri-global-line text-text-accent' +} + +function findProviderConnection(connections: Connection[], providerId?: string) { + if (!providerId) return undefined + return [ + ...connections.filter( + (connection) => connection.providerId === providerId && connection.status !== 'revoked', + ), + ].sort( + (left, right) => + CONNECTION_STATUS_PRIORITY[left.status] - CONNECTION_STATUS_PRIORITY[right.status] || + right.updatedAt.localeCompare(left.updatedAt), + )[0] +} + +function findConnectionById(connections: Connection[], connectionId: string) { + return [...connections.filter((connection) => connection.id === connectionId)].sort( + (left, right) => + right.version - left.version || + right.updatedAt.localeCompare(left.updatedAt) || + CONNECTION_STATUS_PRIORITY[left.status] - CONNECTION_STATUS_PRIORITY[right.status], + )[0] +} + +function getAuthFields(provider: Provider, authKind: ConnectionAuthKind) { + const configurableFields = provider.configuration.filter( + (field) => + provider.id !== FIRECRAWL_PROVIDER_ID || !FIRECRAWL_FIXED_FIELD_NAMES.has(field.name), + ) + if (authKind === 'endpoint') { + return configurableFields.filter((field) => !field.secret) + } + + return configurableFields +} + +function getSupportedAuthKinds(provider: Provider) { + const supported: ConnectionAuthKind[] = [] + if (provider.authKinds.includes('api-key') && getAuthFields(provider, 'api-key').length) + supported.push('api-key') + if ( + provider.authKinds.includes('endpoint') && + getAuthFields(provider, 'endpoint').some((field) => field.format === 'uri') + ) + supported.push('endpoint') + return supported +} + +function SourceTypeSelector({ + value, + onChange, +}: { + value: SourceType + onChange: (value: SourceType) => void +}) { + const { t } = useTranslation('dataset') + const options = [ + { icon: 'i-ri-global-line', key: 'websiteCrawl' as const }, + { icon: 'i-ri-file-text-line', key: 'onlineDocuments' as const }, + { icon: 'i-ri-hard-drive-3-line', key: 'onlineDrive' as const }, + ] + + return ( +
+ + {t(($) => $['newKnowledge.sourceTypeLabel'])} + +
+ {options.map((option) => ( + + ))} +
+
+ ) +} + +function ProviderSelector({ + onChange, + providers, + value, +}: { + onChange: (providerId: string) => void + providers: Provider[] + value?: string +}) { + const { t } = useTranslation('dataset') + + return ( +
+ {t(($) => $['newKnowledge.providerLabel'])} +
+ + {t(($) => $['newKnowledge.providerLabel'])} + + + {t(($) => $['newKnowledge.moreProviders'])} + + +
+
+ {providers.map((provider) => ( + + ))} +
+
+ ) +} + +function ProviderFieldControl({ + field, + setValues, + values, +}: { + field: ProviderField + setValues: React.Dispatch>> + values: Record +}) { + const { t } = useTranslation('dataset') + const generatedId = useId() + const inputId = `${generatedId}-input` + const descriptionId = field.description ? `${generatedId}-description` : undefined + const label = humanizeFieldName(field.name) + const sharedProps = { + 'aria-describedby': descriptionId, + id: inputId, + required: field.required, + value: values[field.name] ?? '', + onChange: (event: React.ChangeEvent) => + setValues((current) => ({ ...current, [field.name]: event.target.value })), + } + + return ( +
+ + {field.type === 'boolean' ? ( + + ) : ( + + )} + {field.description && ( +

+ {field.description} +

+ )} +
+ ) +} + +function ProviderConnected({ provider }: { provider: Provider }) { + const { t } = useTranslation('dataset') + + return ( +
+ + + +

+ {t(($) => $['newKnowledge.providerConnected'], { + provider: provider.displayName, + })} +

+

+ {t(($) => $['newKnowledge.crawlSetupUnavailableDescription'])} +

+
+ ) +} + +function ConnectionForm({ + knowledgeSpaceId, + onConnected, + onReconcile, + provider, +}: { + knowledgeSpaceId: string + onConnected: (connection: Connection) => void + onReconcile: () => Promise + provider: Provider +}) { + const { t } = useTranslation('dataset') + const supportedAuthKinds = getSupportedAuthKinds(provider) + const [authKind, setAuthKind] = useState(supportedAuthKinds[0] ?? 'api-key') + const [configuration, setConfiguration] = useState>({}) + const [credentials, setCredentials] = useState>({}) + const [error, setError] = useState(false) + const [pending, setPending] = useState(false) + const visibleFields = getAuthFields(provider, authKind) + + const changeAuthKind = (nextAuthKind: ConnectionAuthKind) => { + if (nextAuthKind !== authKind) setCredentials({}) + setAuthKind(nextAuthKind) + } + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault() + if (pending) return + + const missingRequiredField = visibleFields.some((field) => { + const values = field.secret ? credentials : configuration + return field.required && !values[field.name]?.trim() + }) + if (missingRequiredField) return + + setError(false) + setPending(true) + try { + const fixedConfiguration = + provider.id === FIRECRAWL_PROVIDER_ID + ? Object.fromEntries( + provider.configuration + .filter((field) => FIRECRAWL_FIXED_FIELD_NAMES.has(field.name)) + .map((field) => [ + field.name, + FIRECRAWL_CONFIGURATION[field.name as keyof typeof FIRECRAWL_CONFIGURATION], + ]), + ) + : {} + const safeConfiguration = { + ...fixedConfiguration, + ...Object.fromEntries( + visibleFields + .filter((field) => !field.secret && configuration[field.name]?.trim()) + .map((field) => [field.name, fieldValue(configuration[field.name] ?? '', field.type)]), + ), + } + const secretCredentials = Object.fromEntries( + visibleFields + .filter((field) => field.secret && credentials[field.name]?.trim()) + .map((field) => [field.name, fieldValue(credentials[field.name] ?? '', field.type)]), + ) + const createdConnection = + await consoleClient.knowledgeFs.postKnowledgeSpacesByIdSourceConnections({ + body: { + authKind, + configuration: safeConfiguration, + credentials: secretCredentials, + name: provider.displayName, + providerId: provider.id, + }, + params: { id: knowledgeSpaceId }, + }) + setCredentials({}) + onConnected(createdConnection) + } catch { + setCredentials({}) + let reconciledConnection: Connection | undefined + try { + reconciledConnection = await onReconcile() + } catch { + reconciledConnection = undefined + } + if (!reconciledConnection) setError(true) + } finally { + setPending(false) + } + } + + return ( +
+ {supportedAuthKinds.length > 1 && ( +
+ + {t(($) => $['newKnowledge.authenticationMethod'])} + +
+ {supportedAuthKinds.map((kind) => ( + + ))} +
+
+ )} +
+ {visibleFields.map((field) => ( + + ))} +
+ {error && ( +

+ {t(($) => $['newKnowledge.connectionFailed'], { + provider: provider.displayName, + })} +

+ )} + +
+ ) +} + +function UnconfiguredProvider({ + knowledgeSpaceId, + onConnected, + onReconcile, + provider, +}: { + knowledgeSpaceId: string + onConnected: (connection: Connection) => void + onReconcile: () => Promise + provider: Provider +}) { + const { t } = useTranslation('dataset') + const [configuring, setConfiguring] = useState(false) + + if (configuring) + return ( + + ) + + return ( +
+ + + +

+ {t(($) => $['newKnowledge.providerNotConfigured'], { + provider: provider.displayName, + })} +

+

+ {t(($) => $['newKnowledge.providerNotConfiguredDescription'], { + provider: provider.displayName, + })} +

+ +
+ ) +} + +function ConnectionProblem({ + connection, + knowledgeSpaceId, + onConnected, + onReconcile, + onReconfigure, + provider, +}: { + connection: Connection + knowledgeSpaceId: string + onConnected: (connection: Connection) => void + onReconcile: () => Promise + onReconfigure: () => Promise + provider: Provider +}) { + const { t } = useTranslation('dataset') + const { t: tCommon } = useTranslation('common') + const [pendingAction, setPendingAction] = useState<'refresh' | 'reconfigure'>() + const [error, setError] = useState(false) + + const refresh = async () => { + if (pendingAction) return + setPendingAction('refresh') + setError(false) + try { + const refreshed = + await consoleClient.knowledgeFs.postKnowledgeSpacesByIdSourceConnectionsByConnectionIdRefresh( + { + body: { expectedVersion: connection.version }, + params: { connectionId: connection.id, id: knowledgeSpaceId }, + }, + ) + onConnected(refreshed) + } catch { + let reconciledConnection: Connection | undefined + try { + reconciledConnection = await onReconcile() + } catch { + reconciledConnection = undefined + } + if (!reconciledConnection) setError(true) + } finally { + setPendingAction(undefined) + } + } + + const reconfigure = async () => { + if (pendingAction) return + setPendingAction('reconfigure') + setError(false) + try { + await onReconfigure() + } catch { + setError(true) + } finally { + setPendingAction(undefined) + } + } + + return ( +
+

+ {t(($) => $['newKnowledge.connectionNeedsAttention'], { + provider: provider.displayName, + })} +

+

+ {t(($) => $['newKnowledge.connectionNeedsAttentionDescription'], { + provider: provider.displayName, + })} +

+ {error && ( +

+ {t(($) => $['newKnowledge.connectionRefreshFailed'])} +

+ )} +
+ + +
+
+ ) +} + +function ProvisioningConnection({ + onReconcile, + provider, +}: { + onReconcile: () => Promise + provider: Provider +}) { + const { t } = useTranslation('dataset') + const [pending, setPending] = useState(false) + const [error, setError] = useState(false) + + const refresh = async () => { + if (pending) return + setPending(true) + setError(false) + try { + const reconciledConnection = await onReconcile() + if (!reconciledConnection) setError(true) + } catch { + setError(true) + } finally { + setPending(false) + } + } + + return ( +
+

+ {t(($) => $['newKnowledge.connectionProvisioning'], { + provider: provider.displayName, + })} +

+ {error && ( +

+ {t(($) => $['newKnowledge.connectionRefreshFailed'])} +

+ )} + +
+ ) +} + +export function AddSourcePage({ knowledgeSpaceId }: { knowledgeSpaceId: string }) { + const { t } = useTranslation('dataset') + const queryClient = useQueryClient() + const [sourceType, setSourceType] = useState('websiteCrawl') + const [selectedProviderId, setSelectedProviderId] = useState() + const [ignoredConnectionIds, setIgnoredConnectionIds] = useState>(() => new Set()) + const providersQuery = useQuery( + consoleQuery.knowledgeFs.getSourceProviders.queryOptions({ + input: {}, + context: { silent: true }, + retry: false, + }), + ) + const connectionsQuery = useInfiniteQuery( + consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSourceConnections.infiniteOptions({ + context: { silent: true }, + input: (pageParam) => ({ + params: { id: knowledgeSpaceId }, + query: { + limit: CONNECTION_PAGE_SIZE, + ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}), + }, + }), + getNextPageParam: (lastPage) => lastPage.nextCursor, + initialPageParam: null as string | null, + retry: false, + }), + ) + const providers = useMemo( + () => + (providersQuery.data?.items ?? []).filter((candidate) => + candidate.capabilities.includes('website-crawl'), + ), + [providersQuery.data?.items], + ) + const provider = + providers.find((candidate) => candidate.id === selectedProviderId) ?? + providers.find((candidate) => candidate.id === FIRECRAWL_PROVIDER_ID) ?? + providers[0] + const remoteConnections = connectionsQuery.data?.pages.flatMap((page) => page.items) ?? [] + const usableRemoteConnections = remoteConnections.filter( + (candidate) => candidate.status !== 'revoked' && !ignoredConnectionIds.has(candidate.id), + ) + const remoteConnection = findProviderConnection(usableRemoteConnections, provider?.id) + const [connectionOverride, setConnectionOverride] = useState() + const matchingRemoteConnection = connectionOverride + ? usableRemoteConnections.find((candidate) => candidate.id === connectionOverride.id) + : undefined + const connection = useMemo(() => { + const localConnection = connectionOverride + if (!localConnection || localConnection.providerId !== provider?.id) return remoteConnection + if (!matchingRemoteConnection) return localConnection + if (matchingRemoteConnection.id === localConnection.id) { + if (matchingRemoteConnection.version > localConnection.version) + return matchingRemoteConnection + if (matchingRemoteConnection.version < localConnection.version) return localConnection + if (matchingRemoteConnection.updatedAt > localConnection.updatedAt) + return matchingRemoteConnection + if (matchingRemoteConnection.updatedAt < localConnection.updatedAt) return localConnection + if ( + CONNECTION_STATUS_PRIORITY[matchingRemoteConnection.status] < + CONNECTION_STATUS_PRIORITY[localConnection.status] + ) + return matchingRemoteConnection + } + return localConnection + }, [connectionOverride, matchingRemoteConnection, provider?.id, remoteConnection]) + const supportsDirectConnection = provider ? getSupportedAuthKinds(provider).length > 0 : false + const { + fetchNextPage: fetchNextConnectionPage, + hasNextPage: hasNextConnectionPage, + isFetchingNextPage: isFetchingNextConnectionPage, + refetch: refetchConnections, + } = connectionsQuery + + useEffect(() => { + if ( + hasNextConnectionPage && + !isFetchingNextConnectionPage && + !connectionsQuery.isFetchNextPageError + ) + void fetchNextConnectionPage() + }, [ + connectionsQuery.isFetchNextPageError, + fetchNextConnectionPage, + hasNextConnectionPage, + isFetchingNextConnectionPage, + ]) + + const rememberConnection = useCallback( + (updatedConnection: Connection) => { + if (updatedConnection.status === 'revoked') { + setIgnoredConnectionIds((current) => new Set(current).add(updatedConnection.id)) + setConnectionOverride(undefined) + } else { + setIgnoredConnectionIds((current) => { + if (!current.has(updatedConnection.id)) return current + const next = new Set(current) + next.delete(updatedConnection.id) + return next + }) + setConnectionOverride(updatedConnection) + } + void queryClient.invalidateQueries({ + queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSourceConnections.key(), + }) + }, + [queryClient], + ) + + const reconcileConnection = useCallback(async () => { + if (connection) setConnectionOverride(connection) + const retryDelays = connection ? [0] : CONNECTION_RECONCILIATION_RETRY_DELAYS + let reconciliationError: Error | undefined + + for (const retryDelay of retryDelays) { + if (retryDelay) await new Promise((resolve) => setTimeout(resolve, retryDelay)) + try { + const refreshed = await refetchConnections() + if (refreshed.error) throw refreshed.error + reconciliationError = undefined + const refreshedConnections = ( + refreshed.data?.pages.flatMap((page) => page.items) ?? [] + ).filter( + (candidate) => candidate.status !== 'revoked' && !ignoredConnectionIds.has(candidate.id), + ) + const refreshedCurrentConnection = connection + ? findConnectionById(refreshedConnections, connection.id) + : undefined + const updatedConnection = connection + ? refreshedCurrentConnection + ? findConnectionById([connection, refreshedCurrentConnection], connection.id) + : undefined + : findProviderConnection(refreshedConnections, provider?.id) + if (updatedConnection) { + setConnectionOverride(updatedConnection) + return updatedConnection + } + } catch (error) { + reconciliationError = + error instanceof Error ? error : new Error('Connection reconciliation failed') + } + } + + if (reconciliationError) throw new Error(reconciliationError.message) + return undefined + }, [connection, ignoredConnectionIds, provider?.id, refetchConnections]) + + const reconfigureConnection = useCallback(async () => { + if (!connection) return + await consoleClient.knowledgeFs.deleteKnowledgeSpacesByIdSourceConnectionsByConnectionId({ + params: { connectionId: connection.id, id: knowledgeSpaceId }, + query: { expectedVersion: connection.version }, + }) + setIgnoredConnectionIds((current) => new Set(current).add(connection.id)) + setConnectionOverride(undefined) + await queryClient.invalidateQueries({ + queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSourceConnections.key(), + }) + }, [connection, knowledgeSpaceId, queryClient]) + + const loadingConnections = + connectionsQuery.isPending || + (!connectionsQuery.isFetchNextPageError && + (connectionsQuery.hasNextPage || connectionsQuery.isFetchingNextPage)) + if (providersQuery.isPending || loadingConnections) + return ( +
+ +
+ ) + + const queryError = + providersQuery.error || connectionsQuery.error || connectionsQuery.isFetchNextPageError + + return ( +
+
+

+ {t(($) => $['newKnowledge.addSource'])} +

+

+ {t(($) => $['newKnowledge.addSourceDescription'])} +

+
+
+ + {sourceType === 'websiteCrawl' ? ( + <> + + {queryError ? ( +
+

+ {t(($) => $['newKnowledge.providerLoadFailed'])} +

+ +
+ ) : !provider ? ( +
+ {t(($) => $['newKnowledge.providerUnavailable'])} +
+ ) : !provider.available || !supportsDirectConnection ? ( +
+

{provider.displayName}

+

+ {provider.unavailableReason ?? t(($) => $['newKnowledge.providerUnavailable'])} +

+
+ ) : connection?.status === 'active' ? ( + + ) : connection?.status === 'provisioning' ? ( + + ) : connection ? ( + + ) : ( + + )} + + ) : ( +
+

+ {t(($) => $[`newKnowledge.${sourceType}`])} +

+

+ {t(($) => $['newKnowledge.providerUnavailable'])} +

+
+ )} +
+ + {t(($) => $['newKnowledge.cancelAddSource'])} + + +
+
+
+ ) +} diff --git a/web/features/new-rag/routes.ts b/web/features/new-rag/routes.ts index 7d27d9eb634..23b4c5bd95c 100644 --- a/web/features/new-rag/routes.ts +++ b/web/features/new-rag/routes.ts @@ -12,3 +12,6 @@ export const newKnowledgeDetailPath = (knowledgeSpaceId: string) => export const newKnowledgeDocumentsPath = (knowledgeSpaceId: string) => `/datasets/new/${knowledgeSpaceId}/documents` + +export const newKnowledgeAddSourcePath = (knowledgeSpaceId: string) => + `/datasets/new/${knowledgeSpaceId}/sources/new` diff --git a/web/features/new-rag/sources-page.tsx b/web/features/new-rag/sources-page.tsx new file mode 100644 index 00000000000..91eaa20e90e --- /dev/null +++ b/web/features/new-rag/sources-page.tsx @@ -0,0 +1,735 @@ +'use client' + +import type { Source } from '@dify/contracts/knowledge-fs/types.gen' +import type { StatusDotStatus } from '@langgenius/dify-ui/status-dot' +import { + AlertDialog, + AlertDialogActions, + AlertDialogCancelButton, + AlertDialogConfirmButton, + AlertDialogContent, + AlertDialogDescription, + AlertDialogTitle, +} from '@langgenius/dify-ui/alert-dialog' +import { Button } from '@langgenius/dify-ui/button' +import { Checkbox } from '@langgenius/dify-ui/checkbox' +import { cn } from '@langgenius/dify-ui/cn' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLinkItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@langgenius/dify-ui/dropdown-menu' +import { StatusDot } from '@langgenius/dify-ui/status-dot' +import { toast } from '@langgenius/dify-ui/toast' +import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query' +import { useAtomValue } from 'jotai' +import { useEffect, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Loading from '@/app/components/base/loading' +import { workspacePermissionKeysAtom } from '@/context/permission-state' +import Link from '@/next/link' +import { consoleClient, consoleQuery } from '@/service/client' +import { hasPermission } from '@/utils/permission' +import { newKnowledgeAddSourcePath } from './routes' + +type SourceStatus = Source['status'] +type SourceFilter = SourceStatus | 'all' +type SourceSort = 'name-asc' | 'name-desc' + +const PAGE_SIZE = 50 +const MAX_AUTO_FILTER_PAGES = 4 +const SOURCE_POLL_INTERVAL = 3000 + +const statusDotStatus: Record = { + active: 'success', + syncing: 'normal', + disabled: 'disabled', + error: 'error', +} + +function metadataString(metadata: Source['metadata'], key: string) { + const value = metadata[key] + return typeof value === 'string' && value.trim() ? value : undefined +} + +function createIdempotencyKey() { + return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}` +} + +function getOpenableSourceUri(uri: string) { + try { + const url = new URL(uri) + return url.protocol === 'http:' || url.protocol === 'https:' ? uri : undefined + } catch { + return undefined + } +} + +function getCurrentSource(source: Source, sourceOverride?: Source) { + if (!sourceOverride || sourceOverride.id !== source.id) return source + const sourceVersion = source.version ?? -1 + const overrideVersion = sourceOverride.version ?? -1 + if (sourceVersion > overrideVersion) return source + if (sourceVersion < overrideVersion) return sourceOverride + return source.updatedAt > sourceOverride.updatedAt ? source : sourceOverride +} + +type SourceAction = 'remove' | 'sync' | 'toggle' + +function SourceActions({ + canEdit, + canSync, + onRemove, + onSync, + onToggle, + pendingAction, + source, +}: { + canEdit: boolean + canSync: boolean + onRemove: () => Promise + onSync: () => Promise + onToggle: () => Promise + pendingAction?: SourceAction + source: Source +}) { + const { t } = useTranslation('dataset') + const { t: tCommon } = useTranslation('common') + const [removeDialogOpen, setRemoveDialogOpen] = useState(false) + const sourceUri = getOpenableSourceUri(source.uri) + + if (!canEdit && !canSync && !sourceUri) return null + + return ( + <> + + $['newKnowledge.sourceActions'], { name: source.name })} + disabled={Boolean(pendingAction)} + className="flex size-7 items-center justify-center rounded-md text-text-tertiary outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid disabled:cursor-not-allowed disabled:text-text-disabled" + > + + + + {canSync && ( + void onSync()} className="gap-2 px-3"> + + {t(($) => $['newKnowledge.syncNow'])} + + )} + {sourceUri && ( + $['operation.openInNewTab'])} + href={sourceUri} + target="_blank" + rel="noopener noreferrer" + /> + } + className="gap-2 px-3" + > + + {tCommon(($) => $['operation.openInNewTab'])} + + )} + {canEdit && ( + <> + void onToggle()} className="gap-2 px-3"> + + {source.status === 'disabled' + ? t(($) => $.enable) + : t(($) => $['newKnowledge.disableSource'])} + + + setRemoveDialogOpen(true)} + variant="destructive" + className="gap-2 px-3" + > + + {t(($) => $['newKnowledge.removeSource'])} + + + )} + + + + +
+ + {tCommon(($) => $['operation.deleteConfirmTitle'])} + + + {tCommon(($) => $['operation.confirmAction'])} + +
+ + + {tCommon(($) => $['operation.cancel'])} + + + void onRemove().then((removed) => { + if (removed) setRemoveDialogOpen(false) + }) + } + > + {t(($) => $['newKnowledge.removeSource'])} + + +
+
+ + ) +} + +function SourceRow({ + canEdit, + canSync, + checked, + knowledgeSpaceId, + onCheckedChange, + onRemoved, + onSourceChange, + source, +}: { + canEdit: boolean + canSync: boolean + checked: boolean + knowledgeSpaceId: string + onCheckedChange: (checked: boolean) => void + onRemoved: () => void + onSourceChange: (source: Source) => void + source: Source +}) { + const { t } = useTranslation('dataset') + const { t: tCommon } = useTranslation('common') + const queryClient = useQueryClient() + const [pendingAction, setPendingAction] = useState() + const providerName = metadataString(source.metadata, 'providerName') + const syncPolicy = metadataString(source.metadata, 'syncPolicy') + const lastSync = metadataString(source.metadata, 'lastSyncedAt') + const typeLabel = t(($) => $[`newKnowledge.sourceType.${source.type}`]) + + const runAction = async ( + action: SourceAction, + mutation: () => Promise, + onAccepted?: (result: Result) => void, + ) => { + if (pendingAction) return false + setPendingAction(action) + try { + let result: Result + try { + result = await mutation() + } catch { + toast.error(t(($) => $['newKnowledge.sourcesErrorDescription'])) + try { + await queryClient.invalidateQueries({ + queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSources.key(), + }) + } catch { + return false + } + return false + } + onAccepted?.(result) + + try { + await queryClient.invalidateQueries({ + queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSources.key(), + }) + } catch { + // The accepted mutation is already reflected by the list-owner state. + } + return true + } finally { + setPendingAction(undefined) + } + } + + const syncSource = () => + runAction( + 'sync', + () => + consoleClient.knowledgeFs.postKnowledgeSpacesByIdSourcesBySourceIdSync({ + headers: { 'Idempotency-Key': createIdempotencyKey() }, + params: { id: knowledgeSpaceId, sourceId: source.id }, + }), + () => onSourceChange({ ...source, status: 'syncing' }), + ) + + const toggleSource = () => + runAction( + 'toggle', + () => + consoleClient.knowledgeFs.patchKnowledgeSpacesByIdSourcesBySourceId({ + body: { + ...(source.version === undefined ? {} : { expectedVersion: source.version }), + status: source.status === 'disabled' ? 'active' : 'disabled', + }, + params: { id: knowledgeSpaceId, sourceId: source.id }, + }), + onSourceChange, + ) + + const removeSource = () => + runAction( + 'remove', + async () => { + if (source.version === undefined) throw new Error('Source version is required') + return consoleClient.knowledgeFs.deleteKnowledgeSpacesByIdSourcesBySourceId({ + body: { expectedRevision: source.version }, + headers: { 'idempotency-key': createIdempotencyKey() }, + params: { id: knowledgeSpaceId, sourceId: source.id }, + query: { documents: 'keep' }, + }) + }, + onRemoved, + ) + + return ( + + + + + +
+ +
+

{source.name}

+
+
+ + +

{providerName ?? typeLabel}

+ {providerName &&

{typeLabel}

} + + + + + {t(($) => $[`newKnowledge.sourceStatus.${source.status}`])} + + + + {syncPolicy ?? '—'} + + + {source.status === 'error' ? ( + + + {t(($) => $['newKnowledge.sourceSyncFailed'])} + + ) : ( + (lastSync ?? '—') + )} + + +
+ {canSync && source.status === 'error' && ( + + )} + +
+ + + ) +} + +function SourcesEmpty({ + canAddSource, + knowledgeSpaceId, +}: { + canAddSource: boolean + knowledgeSpaceId: string +}) { + const { t } = useTranslation('dataset') + + return ( +
+
+ + + + + + +
+

+ {t(($) => $['newKnowledge.sourcesEmptyTitle'])} +

+

+ {t(($) => $['newKnowledge.sourcesEmptyDescription'])} +

+ {canAddSource && ( + + + {t(($) => $['newKnowledge.addSource'])} + + )} +
+ ) +} + +export function SourcesPage({ knowledgeSpaceId }: { knowledgeSpaceId: string }) { + const { t } = useTranslation('dataset') + const { t: tCommon } = useTranslation('common') + const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) + const canManageSources = hasPermission(workspacePermissionKeys, 'dataset.external.connect') + const [filter, setFilter] = useState('all') + const [search, setSearch] = useState('') + const [sort, setSort] = useState() + const [selectedSourceIds, setSelectedSourceIds] = useState>(() => new Set()) + const [sourceOverrides, setSourceOverrides] = useState>({}) + const [removedSourceIds, setRemovedSourceIds] = useState>(() => new Set()) + const sourcesQuery = useInfiniteQuery( + consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSources.infiniteOptions({ + input: (pageParam) => ({ + params: { id: knowledgeSpaceId }, + query: { + limit: PAGE_SIZE, + ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}), + }, + }), + getNextPageParam: (lastPage) => lastPage.nextCursor, + initialPageParam: null as string | null, + refetchInterval: (query) => + query.state.data?.pages.some((page) => + page.items.some( + (source) => + !removedSourceIds.has(source.id) && + getCurrentSource(source, sourceOverrides[source.id]).status === 'syncing', + ), + ) + ? SOURCE_POLL_INTERVAL + : false, + }), + ) + const remoteSources = sourcesQuery.data?.pages.flatMap((page) => page.items) + const sources = useMemo( + () => + (remoteSources ?? []) + .filter((source) => !removedSourceIds.has(source.id)) + .map((source) => getCurrentSource(source, sourceOverrides[source.id])), + [remoteSources, removedSourceIds, sourceOverrides], + ) + const loadedPageCount = sourcesQuery.data?.pages.length ?? 0 + const filteredSources = useMemo(() => { + const normalizedSearch = search.trim().toLocaleLowerCase() + const nextSources = (sources ?? []).filter((source) => { + if (filter !== 'all' && source.status !== filter) return false + if (!normalizedSearch) return true + return `${source.name} ${source.uri}`.toLocaleLowerCase().includes(normalizedSearch) + }) + if (!sort) return nextSources + return [...nextSources].sort((left, right) => { + const result = left.name.localeCompare(right.name) + return sort === 'name-asc' ? result : -result + }) + }, [filter, search, sort, sources]) + const localTransformActive = filter !== 'all' || Boolean(search.trim()) || Boolean(sort) + const canAutoCompleteFilteredResults = + localTransformActive && loadedPageCount < MAX_AUTO_FILTER_PAGES + const completingFilteredResults = + canAutoCompleteFilteredResults && + !sourcesQuery.isFetchNextPageError && + (sourcesQuery.hasNextPage || sourcesQuery.isFetchingNextPage) + const allFilteredSourcesSelected = + filteredSources.length > 0 && + filteredSources.every((source) => selectedSourceIds.has(source.id)) + const someFilteredSourcesSelected = filteredSources.some((source) => + selectedSourceIds.has(source.id), + ) + const { + fetchNextPage: fetchNextSourcePage, + hasNextPage: hasNextSourcePage, + isFetchingNextPage: isFetchingNextSourcePage, + } = sourcesQuery + + useEffect(() => { + if ( + canAutoCompleteFilteredResults && + hasNextSourcePage && + !isFetchingNextSourcePage && + !sourcesQuery.isFetchNextPageError + ) + void fetchNextSourcePage() + }, [ + canAutoCompleteFilteredResults, + fetchNextSourcePage, + hasNextSourcePage, + isFetchingNextSourcePage, + sourcesQuery.isFetchNextPageError, + ]) + + return ( +
+
+
+

+ {t(($) => $['newKnowledge.sources'])} +

+

+ {t(($) => $['newKnowledge.sourcesDescription'])} +

+
+
+ {sourcesQuery.isPending ? ( +
+ +
+ ) : sourcesQuery.error && !sourcesQuery.data ? ( +
+ +

+ {t(($) => $['newKnowledge.sourcesErrorTitle'])} +

+

+ {t(($) => $['newKnowledge.sourcesErrorDescription'])} +

+ +
+ ) : !sources?.length && !sourcesQuery.hasNextPage ? ( + + ) : ( + <> +
+ + + + {canManageSources && ( + + + {t(($) => $['newKnowledge.addSource'])} + + )} +
+
+ + + + + + + + + + + + + {filteredSources.map((source) => ( + { + setRemovedSourceIds((current) => new Set(current).add(source.id)) + setSelectedSourceIds((current) => { + if (!current.has(source.id)) return current + const next = new Set(current) + next.delete(source.id) + return next + }) + }} + onSourceChange={(updatedSource) => + setSourceOverrides((current) => ({ + ...current, + [updatedSource.id]: updatedSource, + })) + } + onCheckedChange={(checked) => { + setSelectedSourceIds((current) => { + const next = new Set(current) + if (checked) next.add(source.id) + else next.delete(source.id) + return next + }) + }} + /> + ))} + +
+ $['operation.selectAll'])} + checked={allFilteredSourcesSelected} + indeterminate={someFilteredSourcesSelected && !allFilteredSourcesSelected} + onCheckedChange={(checked) => { + setSelectedSourceIds((current) => { + const next = new Set(current) + for (const source of filteredSources) { + if (checked) next.add(source.id) + else next.delete(source.id) + } + return next + }) + }} + /> + + + + {t(($) => $['metadata.createMetadata.type'])} + {t(($) => $['newKnowledge.statusColumn'])} + {t(($) => $['newKnowledge.syncPolicyColumn'])} + + {t(($) => $['newKnowledge.lastSyncColumn'])} + $['newKnowledge.actionsColumn'])} /> +
+ {!filteredSources.length && + !completingFilteredResults && + !sourcesQuery.isFetchNextPageError && ( +

+ {t(($) => $['newKnowledge.noMatchingSources'])} +

+ )} + {!filteredSources.length && completingFilteredResults && ( +
+ +
+ )} +
+ {sourcesQuery.isFetchNextPageError ? ( +
+ + {t(($) => $['newKnowledge.sourcesErrorDescription'])} + + +
+ ) : sourcesQuery.hasNextPage && !completingFilteredResults ? ( +
+ +
+ ) : null} + + )} +
+ ) +} diff --git a/web/i18n/ar-TN/dataset.json b/web/i18n/ar-TN/dataset.json index 9a978bea93b..f9bb8d415a6 100644 --- a/web/i18n/ar-TN/dataset.json +++ b/web/i18n/ar-TN/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "مطلوب نموذج إعادة الترتيب لخلط قواعد المعرفة عالية الجودة والاقتصادية.", "mixtureInternalAndExternalTip": "مطلوب نموذج إعادة الترتيب لخلط المعرفة الداخلية والخارجية.", "multimodal": "متعدد الوسائط", + "newKnowledge.actionsColumn": "الإجراءات", + "newKnowledge.addSource": "أضف المصدر", + "newKnowledge.addSourceDescription": "قم بتوصيل مصدر بقاعدة المعرفة هذه - تتم مزامنته تلقائيًا ويظل محدثًا.", + "newKnowledge.allSources": "جميع المصادر", "newKnowledge.appsUnavailable": "— تطبيقات", + "newKnowledge.authKind.api-key": "مفتاح API", + "newKnowledge.authKind.endpoint": "نقطة النهاية", + "newKnowledge.authenticationMethod": "طريقة المصادقة", "newKnowledge.backToList": "العودة إلى قواعد المعرفة", + "newKnowledge.booleanFalse": "لا", + "newKnowledge.booleanTrue": "نعم", + "newKnowledge.cancelAddSource": "إلغاء", "newKnowledge.cardType": "مساحة معرفة", + "newKnowledge.configureProvider": "تكوين {{provider}}", + "newKnowledge.connectProvider": "توصيل {{provider}}", "newKnowledge.connectSource": "ربط مصدر", "newKnowledge.connectSourceDescription": "يبقى المحتوى متزامنًا مع Notion والمواقع الإلكترونية والخدمات الأخرى.", + "newKnowledge.connectingProvider": "جارٍ الاتصال…", + "newKnowledge.connectionFailed": "لم نتمكن من توصيل {{provider}}. أعد إدخال بيانات الاعتماد وحاول مرة أخرى.", + "newKnowledge.connectionNeedsAttention": "يحتاج اتصال {{provider}} إلى الاهتمام", + "newKnowledge.connectionNeedsAttentionDescription": "قم بتحديث الاتصال قبل إضافة مصدر موقع الويب.", + "newKnowledge.connectionProvisioning": "جارٍ الاتصال بـ {{provider}}", + "newKnowledge.connectionRefreshFailed": "لم نتمكن من تحديث هذا الاتصال. حاول ثانية.", + "newKnowledge.crawlSetupUnavailableDescription": "يتم تعطيل تكوين الزحف إلى موقع الويب حتى يتوفر سير عمل الزحف.", "newKnowledge.createFailed": "لم نتمكن من إنشاء قاعدة المعرفة هذه. تحقق من وصولك وحاول مرة أخرى.", "newKnowledge.createTitle": "خلق المعرفة", "newKnowledge.creators": "المنشئون", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "على سبيل المثال سياسة استرداد الأموال، والأسئلة الشائعة حول الشحن، وخطوات التصعيد - تُستخدم لطرح أسئلة دعم العملاء", "newKnowledge.detailErrorDescription": "لم نتمكن من تحميل قاعدة المعرفة هذه. حاول ثانية.", "newKnowledge.detailErrorTitle": "حدث خطأ ما", + "newKnowledge.disableSource": "تعطيل", "newKnowledge.discardDraftConfirm": "تجاهل المسودة", "newKnowledge.discardDraftDescription": "ستُفقد تغييراتك على مسودة قاعدة المعرفة هذه.", "newKnowledge.discardDraftTitle": "تجاهل مسودة قاعدة المعرفة هذه؟", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "اربط مصدرًا وستبقى مستنداته متزامنة ومفهرسة تلقائيًا وجاهزة للاستخدام، من دون إعدادات تحتاج إلى إدارة. ستواصل قواعد المعرفة السابقة العمل كما هي.", "newKnowledge.guideTitle": "تعرّف على قاعدة المعرفة الجديدة ✨", "newKnowledge.illustrationHeadline": "اربط محتواك مرة واحدة — ليجيب كل تطبيق بأحدث معرفة.", + "newKnowledge.lastSyncColumn": "آخر مزامنة", "newKnowledge.learnMore": "معرفة المزيد", "newKnowledge.leavePartialSetupConfirm": "مغادرة الإعداد", "newKnowledge.leavePartialSetupDescription": "تم إنشاء قاعدة المعرفة، لكن تعذّر تأكيد أذوناتها. عند المغادرة سيتم الاحتفاظ بقاعدة المعرفة؛ يمكنك مراجعة الوصول لاحقًا.", "newKnowledge.leavePartialSetupTitle": "مغادرة الإعداد غير المكتمل؟", "newKnowledge.legacy": "قديم", "newKnowledge.loadMore": "تحميل المزيد", + "newKnowledge.moreProviders": "عرض المزيد", "newKnowledge.name": "اسم المعرفة", "newKnowledge.namePlaceholder": "على سبيل المثال دليل دعم العملاء", "newKnowledge.nameRequired": "أدخل اسم قاعدة المعرفة.", "newKnowledge.new": "جديد", "newKnowledge.noDescription": "لا يوجد وصف", + "newKnowledge.noMatchingSources": "لا توجد مصادر تطابق هذا البحث.", "newKnowledge.notFoundDescription": "ربما تم حذف قاعدة المعرفة هذه أو ربما لا يمكنك الوصول إليها.", "newKnowledge.notFoundTitle": "لم يتم العثور على قاعدة المعرفة", + "newKnowledge.onlineDocuments": "المستندات عبر الإنترنت", + "newKnowledge.onlineDrive": "محرك الأقراص عبر الإنترنت", "newKnowledge.permission": "إذن", "newKnowledge.permissionAllMembers": "مساحة العمل · يمكن لجميع الأعضاء العرض والتحرير", "newKnowledge.permissionOnlyMe": "أنا فقط", "newKnowledge.permissionRestricted": "لا تسمح أذونات مساحة العمل الخاصة بك بتغيير هذا الإعداد.", "newKnowledge.permissionUpdateFailed": "تم إنشاء قاعدة المعرفة، لكن تعذّر تأكيد أذوناتها. أعد المحاولة لإكمال الإعداد.", + "newKnowledge.providerConnected": "تم توصيل {{provider}}", + "newKnowledge.providerLabel": "اختر مزودًا", + "newKnowledge.providerLoadFailed": "لم يتمكن الموفرون من التحميل", + "newKnowledge.providerNotConfigured": "{{provider}} لم يتم تكوينه", + "newKnowledge.providerNotConfiguredDescription": "أضف مفتاح API أو عنوان URL لنقطة النهاية للزحف إلى مواقع الويب باستخدام {{provider}}.", + "newKnowledge.providerUnavailable": "هذا الموفر غير متوفر.", "newKnowledge.readOnlyEmpty": "اطلب من محرر مساحة العمل إنشاء أول قاعدة معرفة.", + "newKnowledge.refreshConnectionStatus": "تحديث الحالة", + "newKnowledge.refreshingConnection": "منعش…", + "newKnowledge.removeSource": "قم بإزالة المصدر", + "newKnowledge.retryProviderLoad": "أعد المحاولة", "newKnowledge.routeUnavailable": "سيصبح هذا القسم متاحًا في خطوة الإعداد التالية.", + "newKnowledge.searchSources": "مصادر البحث", + "newKnowledge.sourceActions": "إجراءات {{name}}", + "newKnowledge.sourceColumn": "المصدر", + "newKnowledge.sourceFilterLabel": "تصفية المصادر حسب الحالة", + "newKnowledge.sourceStatus.active": "نشط", + "newKnowledge.sourceStatus.disabled": "معطل", + "newKnowledge.sourceStatus.error": "خطأ", + "newKnowledge.sourceStatus.syncing": "المزامنة", + "newKnowledge.sourceSyncFailed": "فشل", + "newKnowledge.sourceType.connector": "التطبيق المتصل", + "newKnowledge.sourceType.object-storage": "محرك الأقراص عبر الإنترنت", + "newKnowledge.sourceType.upload": "تحميل", + "newKnowledge.sourceType.web": "الزحف إلى موقع الويب", + "newKnowledge.sourceTypeLabel": "نوع المصدر", "newKnowledge.sources": "المصادر", + "newKnowledge.sourcesDescription": "من أين تأتي المعرفة، ومدى حداثتها، وما إذا كانت المزامنة الأخيرة قد نجحت.", + "newKnowledge.sourcesEmptyDescription": "اربط موقعًا إلكترونيًا أو مساحة عمل أو محرك أقراص — يحافظ Dify على مزامنته وتحديثه، حتى لا يتعطل الاسترجاع أبدًا.", + "newKnowledge.sourcesEmptyTitle": "لا توجد مصادر متصلة بعد", + "newKnowledge.sourcesErrorDescription": "لم نتمكن من تحميل المصادر. حاول ثانية.", + "newKnowledge.sourcesErrorTitle": "تعذر تحميل المصادر", "newKnowledge.startEmpty": "ابدأ فارغًا", "newKnowledge.startEmptyDescription": "أنشئها الآن وأضف المحتوى لاحقًا.", "newKnowledge.startWith": "ابدأ ب", "newKnowledge.startWithHelp": "يمكنك إضافة المزيد من المصادر أو المستندات في أي وقت.", + "newKnowledge.statusColumn": "الحالة", + "newKnowledge.syncNow": "المزامنة الآن", + "newKnowledge.syncPolicyColumn": "سياسة المزامنة", "newKnowledge.tags": "الوسوم", "newKnowledge.unavailableDescription": "KnowledgeFS غير متاح لمساحة العمل هذه حاليًا.", "newKnowledge.unavailableTitle": "المعرفة الجديدة غير متاحة", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "رفع الملفات", "newKnowledge.uploadFilesDescription": "أضف ملفات من جهازك — ستتم فهرستها بمجرد إنشائها.", "newKnowledge.viewLabel": "عرض المعرفة", + "newKnowledge.websiteCrawl": "الزحف إلى موقع الويب", "noExternalKnowledge": "لا توجد واجهة برمجة تطبيقات معرفة خارجية حتى الآن، انقر هنا لإنشاء", "parentMode.fullDoc": "مستند كامل", "parentMode.paragraph": "فقرة", diff --git a/web/i18n/de-DE/dataset.json b/web/i18n/de-DE/dataset.json index b79f6038dd6..6bb834e4569 100644 --- a/web/i18n/de-DE/dataset.json +++ b/web/i18n/de-DE/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Für die Mischung von hochwertigen und wirtschaftlichen Wissensbasen ist das Rerank-Modell erforderlich.", "mixtureInternalAndExternalTip": "Das Rerank-Modell ist für die Mischung von internem und externem Wissen erforderlich.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Aktionen", + "newKnowledge.addSource": "Quelle hinzufügen", + "newKnowledge.addSourceDescription": "Verbinden Sie eine Quelle mit dieser Wissensdatenbank – sie wird automatisch synchronisiert und bleibt aktuell.", + "newKnowledge.allSources": "Alle Quellen", "newKnowledge.appsUnavailable": "— Apps", + "newKnowledge.authKind.api-key": "API-Schlüssel", + "newKnowledge.authKind.endpoint": "Endpunkt", + "newKnowledge.authenticationMethod": "Authentifizierungsmethode", "newKnowledge.backToList": "Zurück zu den Wissensdatenbanken", + "newKnowledge.booleanFalse": "Nein", + "newKnowledge.booleanTrue": "Ja", + "newKnowledge.cancelAddSource": "Abbrechen", "newKnowledge.cardType": "Wissensbereich", + "newKnowledge.configureProvider": "{{provider}} konfigurieren", + "newKnowledge.connectProvider": "Verbinden Sie {{provider}}", "newKnowledge.connectSource": "Quelle verbinden", "newKnowledge.connectSourceDescription": "Inhalte bleiben mit Notion, Websites und anderen Diensten synchron.", + "newKnowledge.connectingProvider": "Verbinden…", + "newKnowledge.connectionFailed": "Wir konnten {{provider}} nicht verbinden. Geben Sie die Anmeldedaten erneut ein und versuchen Sie es erneut.", + "newKnowledge.connectionNeedsAttention": "{{provider}}-Verbindung erfordert Aufmerksamkeit", + "newKnowledge.connectionNeedsAttentionDescription": "Aktualisieren Sie die Verbindung, bevor Sie eine Website-Quelle hinzufügen.", + "newKnowledge.connectionProvisioning": "{{provider}} stellt eine Verbindung her", + "newKnowledge.connectionRefreshFailed": "Wir konnten diese Verbindung nicht aktualisieren. Versuchen Sie es erneut.", + "newKnowledge.crawlSetupUnavailableDescription": "Die Website-Crawling-Konfiguration ist deaktiviert, bis der Crawl-Workflow verfügbar ist.", "newKnowledge.createFailed": "Wir konnten diese Wissensdatenbank nicht erstellen. Überprüfen Sie Ihren Zugang und versuchen Sie es erneut.", "newKnowledge.createTitle": "Wissen schaffen", "newKnowledge.creators": "Ersteller", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "z.B. Rückerstattungsrichtlinien, häufig gestellte Fragen zum Versand und Eskalationsschritte – für Fragen zum Kundensupport verwenden", "newKnowledge.detailErrorDescription": "Diese Wissensdatenbank konnte nicht geladen werden. Versuchen Sie es erneut.", "newKnowledge.detailErrorTitle": "Etwas ist schief gelaufen", + "newKnowledge.disableSource": "Deaktivieren", "newKnowledge.discardDraftConfirm": "Entwurf verwerfen", "newKnowledge.discardDraftDescription": "Ihre Änderungen an diesem Wissensdatenbank-Entwurf gehen verloren.", "newKnowledge.discardDraftTitle": "Diesen Wissensdatenbank-Entwurf verwerfen?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Verbinden Sie eine Quelle, und ihre Dokumente bleiben synchron — automatisch indiziert und sofort einsatzbereit, ohne Verwaltungsaufwand. Ihre bisherigen Wissensdatenbanken funktionieren unverändert weiter.", "newKnowledge.guideTitle": "Lernen Sie die neue Wissensdatenbank kennen ✨", "newKnowledge.illustrationHeadline": "Verbinde deine Inhalte einmal – und jede App antwortet mit dem neuesten Wissen.", + "newKnowledge.lastSyncColumn": "Letzte Synchronisierung", "newKnowledge.learnMore": "Mehr erfahren", "newKnowledge.leavePartialSetupConfirm": "Einrichtung verlassen", "newKnowledge.leavePartialSetupDescription": "Die Wissensdatenbank wurde erstellt, aber ihre Berechtigung konnte nicht bestätigt werden. Beim Verlassen bleibt die Wissensdatenbank erhalten; Sie können den Zugriff später überprüfen.", "newKnowledge.leavePartialSetupTitle": "Unvollständige Einrichtung verlassen?", "newKnowledge.legacy": "Legacy", "newKnowledge.loadMore": "Mehr laden", + "newKnowledge.moreProviders": "Mehr anzeigen", "newKnowledge.name": "Wissensname", "newKnowledge.namePlaceholder": "z.B. Kundendiensthandbuch", "newKnowledge.nameRequired": "Geben Sie einen Namen für die Wissensdatenbank ein.", "newKnowledge.new": "Neu", "newKnowledge.noDescription": "Keine Beschreibung", + "newKnowledge.noMatchingSources": "Keine Quellen passen zu dieser Suche.", "newKnowledge.notFoundDescription": "Diese Wissensdatenbank wurde möglicherweise gelöscht oder Sie haben keinen Zugriff darauf.", "newKnowledge.notFoundTitle": "Wissensdatenbank nicht gefunden", + "newKnowledge.onlineDocuments": "Online-Dokumente", + "newKnowledge.onlineDrive": "Online-Laufwerk", "newKnowledge.permission": "Erlaubnis", "newKnowledge.permissionAllMembers": "Arbeitsbereich · Alle Mitglieder können ihn ansehen und bearbeiten", "newKnowledge.permissionOnlyMe": "Nur ich", "newKnowledge.permissionRestricted": "Ihre Arbeitsbereichsberechtigungen erlauben keine Änderung dieser Einstellung.", "newKnowledge.permissionUpdateFailed": "Die Wissensdatenbank wurde erstellt, aber ihre Berechtigung konnte nicht bestätigt werden. Versuchen Sie es erneut, um die Einrichtung abzuschließen.", + "newKnowledge.providerConnected": "{{provider}} verbunden", + "newKnowledge.providerLabel": "Wählen Sie einen Anbieter", + "newKnowledge.providerLoadFailed": "Anbieter konnten nicht geladen werden", + "newKnowledge.providerNotConfigured": "{{provider}} ist nicht konfiguriert", + "newKnowledge.providerNotConfiguredDescription": "Fügen Sie einen API-Schlüssel oder eine Endpunkt-URL hinzu, um Websites mit {{provider}} zu crawlen.", + "newKnowledge.providerUnavailable": "Dieser Anbieter ist nicht verfügbar.", "newKnowledge.readOnlyEmpty": "Bitten Sie einen Arbeitsbereich-Editor, die erste Wissensdatenbank zu erstellen.", + "newKnowledge.refreshConnectionStatus": "Status aktualisieren", + "newKnowledge.refreshingConnection": "Erfrischend…", + "newKnowledge.removeSource": "Quelle entfernen", + "newKnowledge.retryProviderLoad": "Wiederholen", "newKnowledge.routeUnavailable": "Dieser Abschnitt wird im nächsten Einrichtungsschritt verfügbar.", + "newKnowledge.searchSources": "Quellen durchsuchen", + "newKnowledge.sourceActions": "Aktionen für {{name}}", + "newKnowledge.sourceColumn": "Quelle", + "newKnowledge.sourceFilterLabel": "Quellen nach Status filtern", + "newKnowledge.sourceStatus.active": "Aktiv", + "newKnowledge.sourceStatus.disabled": "Deaktiviert", + "newKnowledge.sourceStatus.error": "Fehler", + "newKnowledge.sourceStatus.syncing": "Synchronisierung", + "newKnowledge.sourceSyncFailed": "Fehlgeschlagen", + "newKnowledge.sourceType.connector": "Verbundene App", + "newKnowledge.sourceType.object-storage": "Online-Laufwerk", + "newKnowledge.sourceType.upload": "Hochladen", + "newKnowledge.sourceType.web": "Website-Crawling", + "newKnowledge.sourceTypeLabel": "Quelltyp", "newKnowledge.sources": "Quellen", + "newKnowledge.sourcesDescription": "Woher das Wissen kommt, wie aktuell es ist und ob die letzte Synchronisierung erfolgreich war.", + "newKnowledge.sourcesEmptyDescription": "Verbinde eine Website, einen Arbeitsbereich oder ein Laufwerk – Dify hält die Inhalte synchron und aktuell, damit der Abruf jederzeit funktioniert.", + "newKnowledge.sourcesEmptyTitle": "Noch keine Quellen verbunden", + "newKnowledge.sourcesErrorDescription": "Wir konnten die Quellen nicht laden. Versuchen Sie es erneut.", + "newKnowledge.sourcesErrorTitle": "Quellen konnten nicht geladen werden", "newKnowledge.startEmpty": "Leer beginnen", "newKnowledge.startEmptyDescription": "Jetzt erstellen und Inhalte später hinzufügen.", "newKnowledge.startWith": "Beginnen Sie mit", "newKnowledge.startWithHelp": "Sie können jederzeit weitere Quellen oder Dokumente hinzufügen.", + "newKnowledge.statusColumn": "Status", + "newKnowledge.syncNow": "Jetzt synchronisieren", + "newKnowledge.syncPolicyColumn": "Synchronisierungsrichtlinie", "newKnowledge.tags": "Tags", "newKnowledge.unavailableDescription": "KnowledgeFS ist für diesen Arbeitsbereich derzeit nicht verfügbar.", "newKnowledge.unavailableTitle": "Neues Wissen ist nicht verfügbar", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Dateien hochladen", "newKnowledge.uploadFilesDescription": "Fügen Sie Dateien von Ihrem Computer hinzu — sie werden beim Erstellen sofort indiziert.", "newKnowledge.viewLabel": "Wissensansicht", + "newKnowledge.websiteCrawl": "Website-Crawling", "noExternalKnowledge": "Es gibt noch keine External Knowledge API, klicken Sie hier, um zu erstellen", "parentMode.fullDoc": "Vollständiges Dokument", "parentMode.paragraph": "Absatz", diff --git a/web/i18n/en-US/dataset.json b/web/i18n/en-US/dataset.json index 900b5891c2f..f302f68d833 100644 --- a/web/i18n/en-US/dataset.json +++ b/web/i18n/en-US/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "The Rerank model is required for mixture of high quality and economical knowledge bases.", "mixtureInternalAndExternalTip": "The Rerank model is required for mixture of internal and external knowledge.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Actions", + "newKnowledge.addSource": "Add source", + "newKnowledge.addSourceDescription": "Connect a source to this knowledge base — it syncs automatically and stays fresh.", + "newKnowledge.allSources": "All sources", "newKnowledge.appsUnavailable": "— apps", + "newKnowledge.authKind.api-key": "API key", + "newKnowledge.authKind.endpoint": "Endpoint", + "newKnowledge.authenticationMethod": "Authentication method", "newKnowledge.backToList": "Back to knowledge bases", + "newKnowledge.booleanFalse": "No", + "newKnowledge.booleanTrue": "Yes", + "newKnowledge.cancelAddSource": "Cancel", "newKnowledge.cardType": "Knowledge space", + "newKnowledge.configureProvider": "Configure {{provider}}", + "newKnowledge.connectProvider": "Connect {{provider}}", "newKnowledge.connectSource": "Connect a source", "newKnowledge.connectSourceDescription": "Content stays in sync with Notion, websites, and other services.", + "newKnowledge.connectingProvider": "Connecting…", + "newKnowledge.connectionFailed": "We couldn't connect {{provider}}. Re-enter the credential and try again.", + "newKnowledge.connectionNeedsAttention": "{{provider}} connection needs attention", + "newKnowledge.connectionNeedsAttentionDescription": "Refresh the connection before adding a website source.", + "newKnowledge.connectionProvisioning": "{{provider}} is connecting", + "newKnowledge.connectionRefreshFailed": "We couldn't refresh this connection. Try again.", + "newKnowledge.crawlSetupUnavailableDescription": "Website crawl configuration is disabled until the crawl workflow is available.", "newKnowledge.createFailed": "We couldn't create this knowledge base. Check your access and try again.", "newKnowledge.createTitle": "Create Knowledge", "newKnowledge.creators": "Creators", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "e.g. Refund policy, shipping FAQs, and escalation steps — use for customer support questions", "newKnowledge.detailErrorDescription": "We couldn't load this knowledge base. Try again.", "newKnowledge.detailErrorTitle": "Something went wrong", + "newKnowledge.disableSource": "Disable", "newKnowledge.discardDraftConfirm": "Discard draft", "newKnowledge.discardDraftDescription": "Your changes to this knowledge base draft will be lost.", "newKnowledge.discardDraftTitle": "Discard this knowledge base draft?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Connect a Source and its Documents stay in sync — indexed automatically and ready to use, with no setup to manage. Your Legacy knowledge bases keep working as-is.", "newKnowledge.guideTitle": "Meet the new Knowledge Base ✨", "newKnowledge.illustrationHeadline": "Connect your content once — every app answers with the freshest knowledge.", + "newKnowledge.lastSyncColumn": "Last sync", "newKnowledge.learnMore": "Learn more", "newKnowledge.leavePartialSetupConfirm": "Leave setup", "newKnowledge.leavePartialSetupDescription": "The knowledge base was created, but its permission could not be confirmed. Leaving keeps the knowledge base; you can review access later.", "newKnowledge.leavePartialSetupTitle": "Leave incomplete setup?", "newKnowledge.legacy": "Legacy", "newKnowledge.loadMore": "Load more", + "newKnowledge.moreProviders": "More providers", "newKnowledge.name": "Knowledge name", "newKnowledge.namePlaceholder": "e.g. Customer Support Handbook", "newKnowledge.nameRequired": "Enter a knowledge base name.", "newKnowledge.new": "New", "newKnowledge.noDescription": "No description", + "newKnowledge.noMatchingSources": "No sources match this search.", "newKnowledge.notFoundDescription": "This knowledge base may have been deleted or you may not have access.", "newKnowledge.notFoundTitle": "Knowledge base not found", + "newKnowledge.onlineDocuments": "Online documents", + "newKnowledge.onlineDrive": "Online drive", "newKnowledge.permission": "Permission", "newKnowledge.permissionAllMembers": "Workspace · all members can view and edit", "newKnowledge.permissionOnlyMe": "Only me", "newKnowledge.permissionRestricted": "Your workspace permissions don't allow changing this setting.", "newKnowledge.permissionUpdateFailed": "The knowledge base was created, but its permission could not be confirmed. Retry to finish setup.", + "newKnowledge.providerConnected": "{{provider}} connected", + "newKnowledge.providerLabel": "Provider", + "newKnowledge.providerLoadFailed": "Providers couldn't load", + "newKnowledge.providerNotConfigured": "{{provider}} is not configured", + "newKnowledge.providerNotConfiguredDescription": "Add an API key or endpoint URL to crawl websites with {{provider}}.", + "newKnowledge.providerUnavailable": "This provider is unavailable.", "newKnowledge.readOnlyEmpty": "Ask a workspace editor to create the first knowledge base.", + "newKnowledge.refreshConnectionStatus": "Refresh status", + "newKnowledge.refreshingConnection": "Refreshing…", + "newKnowledge.removeSource": "Remove source", + "newKnowledge.retryProviderLoad": "Retry", "newKnowledge.routeUnavailable": "This section will become available in the next setup step.", + "newKnowledge.searchSources": "Search sources", + "newKnowledge.sourceActions": "Actions for {{name}}", + "newKnowledge.sourceColumn": "Source", + "newKnowledge.sourceFilterLabel": "Filter sources by status", + "newKnowledge.sourceStatus.active": "Active", + "newKnowledge.sourceStatus.disabled": "Disabled", + "newKnowledge.sourceStatus.error": "Error", + "newKnowledge.sourceStatus.syncing": "Syncing", + "newKnowledge.sourceSyncFailed": "Failed", + "newKnowledge.sourceType.connector": "Connected app", + "newKnowledge.sourceType.object-storage": "Online drive", + "newKnowledge.sourceType.upload": "Upload", + "newKnowledge.sourceType.web": "Website crawl", + "newKnowledge.sourceTypeLabel": "Source type", "newKnowledge.sources": "Sources", + "newKnowledge.sourcesDescription": "Where knowledge comes from, how fresh it is, and whether the last sync succeeded.", + "newKnowledge.sourcesEmptyDescription": "Connect a website, workspace, or drive — Dify keeps it synced and fresh, so retrieval never breaks.", + "newKnowledge.sourcesEmptyTitle": "No sources connected yet", + "newKnowledge.sourcesErrorDescription": "We couldn't load sources. Try again.", + "newKnowledge.sourcesErrorTitle": "Sources couldn't load", "newKnowledge.startEmpty": "Start empty", "newKnowledge.startEmptyDescription": "Create it now, add content later.", "newKnowledge.startWith": "Start with", "newKnowledge.startWithHelp": "You can add more Sources or Documents anytime.", + "newKnowledge.statusColumn": "Status", + "newKnowledge.syncNow": "Sync now", + "newKnowledge.syncPolicyColumn": "Sync policy", "newKnowledge.tags": "Tags", "newKnowledge.unavailableDescription": "KnowledgeFS isn't available for this workspace right now.", "newKnowledge.unavailableTitle": "New Knowledge is unavailable", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Upload files", "newKnowledge.uploadFilesDescription": "Add files from your computer — they're indexed as soon as you create.", "newKnowledge.viewLabel": "Knowledge view", + "newKnowledge.websiteCrawl": "Website crawl", "noExternalKnowledge": "There is no External Knowledge API yet, click here to create", "parentMode.fullDoc": "Full-doc", "parentMode.paragraph": "Paragraph", diff --git a/web/i18n/es-ES/dataset.json b/web/i18n/es-ES/dataset.json index cbfe7f94aad..3360fb3fce6 100644 --- a/web/i18n/es-ES/dataset.json +++ b/web/i18n/es-ES/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Se requiere el modelo de reclasificación para la mezcla de bases de conocimiento de alta calidad y económicas.", "mixtureInternalAndExternalTip": "El modelo de Rerank es necesario para la mezcla de conocimiento interno y externo.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Acciones", + "newKnowledge.addSource": "Agregar fuente", + "newKnowledge.addSourceDescription": "Conecte una fuente a esta base de conocimientos: se sincroniza automáticamente y se mantiene actualizada.", + "newKnowledge.allSources": "Todas las fuentes", "newKnowledge.appsUnavailable": "— aplicaciones", + "newKnowledge.authKind.api-key": "Clave API", + "newKnowledge.authKind.endpoint": "Punto final", + "newKnowledge.authenticationMethod": "Método de autenticación", "newKnowledge.backToList": "Volver a las bases de conocimiento", + "newKnowledge.booleanFalse": "No", + "newKnowledge.booleanTrue": "Sí", + "newKnowledge.cancelAddSource": "Cancelar", "newKnowledge.cardType": "Espacio de conocimiento", + "newKnowledge.configureProvider": "Configurar {{provider}}", + "newKnowledge.connectProvider": "Conectar {{provider}}", "newKnowledge.connectSource": "Conectar una fuente", "newKnowledge.connectSourceDescription": "El contenido se mantiene sincronizado con Notion, sitios web y otros servicios.", + "newKnowledge.connectingProvider": "Conectando…", + "newKnowledge.connectionFailed": "No pudimos conectar {{provider}}. Vuelva a ingresar la credencial e inténtelo nuevamente.", + "newKnowledge.connectionNeedsAttention": "La conexión {{provider}} necesita atención", + "newKnowledge.connectionNeedsAttentionDescription": "Actualiza la conexión antes de agregar una fuente de sitio web.", + "newKnowledge.connectionProvisioning": "{{provider}} se está conectando", + "newKnowledge.connectionRefreshFailed": "No pudimos actualizar esta conexión. Intentar otra vez.", + "newKnowledge.crawlSetupUnavailableDescription": "La configuración de rastreo del sitio web está deshabilitada hasta que el flujo de trabajo de rastreo esté disponible.", "newKnowledge.createFailed": "No pudimos crear esta base de conocimientos. Comprueba tu acceso y vuelve a intentarlo.", "newKnowledge.createTitle": "Crear conocimiento", "newKnowledge.creators": "Creadores", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "p.ej. Política de reembolso, preguntas frecuentes sobre envíos y pasos a seguir: utilícelos para preguntas de atención al cliente", "newKnowledge.detailErrorDescription": "No pudimos cargar esta base de conocimientos. Intentar otra vez.", "newKnowledge.detailErrorTitle": "algo salió mal", + "newKnowledge.disableSource": "Desactivar", "newKnowledge.discardDraftConfirm": "Descartar borrador", "newKnowledge.discardDraftDescription": "Se perderán los cambios realizados en este borrador de base de conocimientos.", "newKnowledge.discardDraftTitle": "¿Descartar este borrador de base de conocimientos?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Conecta una fuente y sus documentos se mantendrán sincronizados, indexados automáticamente y listos para usar, sin nada que administrar. Tus bases de conocimiento anteriores seguirán funcionando igual.", "newKnowledge.guideTitle": "Conoce la nueva base de conocimiento ✨", "newKnowledge.illustrationHeadline": "Conecta tu contenido una vez: cada aplicación responderá con el conocimiento más reciente.", + "newKnowledge.lastSyncColumn": "Última sincronización", "newKnowledge.learnMore": "Más información", "newKnowledge.leavePartialSetupConfirm": "Salir de la configuración", "newKnowledge.leavePartialSetupDescription": "La base de conocimientos se creó, pero no se pudo confirmar su permiso. Si sales, la base de conocimientos se conservará; puedes revisar el acceso más adelante.", "newKnowledge.leavePartialSetupTitle": "¿Salir de la configuración incompleta?", "newKnowledge.legacy": "Anterior", "newKnowledge.loadMore": "Cargar más", + "newKnowledge.moreProviders": "Ver más", "newKnowledge.name": "Nombre del conocimiento", "newKnowledge.namePlaceholder": "por ej. Manual de atención al cliente", "newKnowledge.nameRequired": "Introduzca un nombre para la base de conocimientos.", "newKnowledge.new": "Nuevo", "newKnowledge.noDescription": "Sin descripción", + "newKnowledge.noMatchingSources": "Ninguna fuente coincide con esta búsqueda.", "newKnowledge.notFoundDescription": "Es posible que esta base de conocimientos haya sido eliminada o que no tengas acceso.", "newKnowledge.notFoundTitle": "Base de conocimientos no encontrada", + "newKnowledge.onlineDocuments": "Documentos en línea", + "newKnowledge.onlineDrive": "Unidad en línea", "newKnowledge.permission": "Permiso", "newKnowledge.permissionAllMembers": "Espacio de trabajo · todos los miembros pueden ver y editar", "newKnowledge.permissionOnlyMe": "solo yo", "newKnowledge.permissionRestricted": "Los permisos de su espacio de trabajo no permiten cambiar esta configuración.", "newKnowledge.permissionUpdateFailed": "La base de conocimientos se creó, pero no se pudo confirmar su permiso. Vuelve a intentarlo para finalizar la configuración.", + "newKnowledge.providerConnected": "{{provider}} conectado", + "newKnowledge.providerLabel": "Seleccione un proveedor", + "newKnowledge.providerLoadFailed": "Los proveedores no pudieron cargar", + "newKnowledge.providerNotConfigured": "{{provider}} no está configurado", + "newKnowledge.providerNotConfiguredDescription": "Agregue una clave API o una URL de punto final para rastrear sitios web con {{provider}}.", + "newKnowledge.providerUnavailable": "Este proveedor no está disponible.", "newKnowledge.readOnlyEmpty": "Pide a un editor del espacio de trabajo que cree la primera base de conocimiento.", + "newKnowledge.refreshConnectionStatus": "Estado de actualización", + "newKnowledge.refreshingConnection": "Refrescante…", + "newKnowledge.removeSource": "Eliminar fuente", + "newKnowledge.retryProviderLoad": "Reintentar", "newKnowledge.routeUnavailable": "Esta sección estará disponible en el siguiente paso de configuración.", + "newKnowledge.searchSources": "Buscar fuentes", + "newKnowledge.sourceActions": "Acciones para {{name}}", + "newKnowledge.sourceColumn": "Fuente", + "newKnowledge.sourceFilterLabel": "Filtrar fuentes por estado", + "newKnowledge.sourceStatus.active": "Activo", + "newKnowledge.sourceStatus.disabled": "Deshabilitado", + "newKnowledge.sourceStatus.error": "Error", + "newKnowledge.sourceStatus.syncing": "Sincronización", + "newKnowledge.sourceSyncFailed": "Fallido", + "newKnowledge.sourceType.connector": "Aplicación conectada", + "newKnowledge.sourceType.object-storage": "Unidad en línea", + "newKnowledge.sourceType.upload": "Subir", + "newKnowledge.sourceType.web": "Rastreo del sitio web", + "newKnowledge.sourceTypeLabel": "Tipo de fuente", "newKnowledge.sources": "Fuentes", + "newKnowledge.sourcesDescription": "De dónde proviene el conocimiento, qué tan actualizado está y si la última sincronización fue exitosa.", + "newKnowledge.sourcesEmptyDescription": "Conecta un sitio web, un espacio de trabajo o una unidad: Dify lo mantiene sincronizado y actualizado para que la recuperación nunca falle.", + "newKnowledge.sourcesEmptyTitle": "Aún no hay fuentes conectadas", + "newKnowledge.sourcesErrorDescription": "No pudimos cargar fuentes. Intentar otra vez.", + "newKnowledge.sourcesErrorTitle": "No se pudieron cargar las fuentes", "newKnowledge.startEmpty": "Empezar vacía", "newKnowledge.startEmptyDescription": "Créala ahora y añade contenido más tarde.", "newKnowledge.startWith": "Empezar con", "newKnowledge.startWithHelp": "Puede agregar más fuentes o documentos en cualquier momento.", + "newKnowledge.statusColumn": "Estado", + "newKnowledge.syncNow": "Sincronizar ahora", + "newKnowledge.syncPolicyColumn": "Política de sincronización", "newKnowledge.tags": "Etiquetas", "newKnowledge.unavailableDescription": "KnowledgeFS no está disponible para este espacio de trabajo ahora mismo.", "newKnowledge.unavailableTitle": "El nuevo conocimiento no está disponible", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Subir archivos", "newKnowledge.uploadFilesDescription": "Añade archivos desde tu ordenador; se indexarán en cuanto los crees.", "newKnowledge.viewLabel": "Vista de conocimiento", + "newKnowledge.websiteCrawl": "Rastreo del sitio web", "noExternalKnowledge": "Todavía no hay una API de conocimiento externo, haga clic aquí para crear", "parentMode.fullDoc": "Documento completo", "parentMode.paragraph": "Párrafo", diff --git a/web/i18n/fa-IR/dataset.json b/web/i18n/fa-IR/dataset.json index 3c56899c103..a6de58579d3 100644 --- a/web/i18n/fa-IR/dataset.json +++ b/web/i18n/fa-IR/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "مدل دوباره رتبه‌بندی برای ترکیب پایگاه‌های دانش با کیفیت بالا و اقتصادی لازم است.", "mixtureInternalAndExternalTip": "مدل Rerank برای آمیختگی دانش درونی و بیرونی مورد نیاز است.", "multimodal": "چندوجهی", + "newKnowledge.actionsColumn": "اقدامات", + "newKnowledge.addSource": "اضافه کردن منبع", + "newKnowledge.addSourceDescription": "منبعی را به این پایگاه دانش متصل کنید - به طور خودکار همگام‌سازی می‌شود و تازه می‌ماند.", + "newKnowledge.allSources": "همه منابع", "newKnowledge.appsUnavailable": "— برنامه", + "newKnowledge.authKind.api-key": "کلید API", + "newKnowledge.authKind.endpoint": "نقطه پایانی", + "newKnowledge.authenticationMethod": "روش احراز هویت", "newKnowledge.backToList": "بازگشت به پایگاه های دانش", + "newKnowledge.booleanFalse": "نه", + "newKnowledge.booleanTrue": "بله", + "newKnowledge.cancelAddSource": "لغو", "newKnowledge.cardType": "فضای دانش", + "newKnowledge.configureProvider": "{{provider}} را پیکربندی کنید", + "newKnowledge.connectProvider": "{{provider}} را وصل کنید", "newKnowledge.connectSource": "اتصال منبع", "newKnowledge.connectSourceDescription": "محتوا با Notion، وب‌سایت‌ها و سرویس‌های دیگر همگام می‌ماند.", + "newKnowledge.connectingProvider": "در حال اتصال…", + "newKnowledge.connectionFailed": "ما نتوانستیم {{provider}} را متصل کنیم. اعتبارنامه را دوباره وارد کنید و دوباره امتحان کنید.", + "newKnowledge.connectionNeedsAttention": "اتصال {{provider}} نیاز به توجه دارد", + "newKnowledge.connectionNeedsAttentionDescription": "قبل از افزودن منبع وب سایت، اتصال را تازه کنید.", + "newKnowledge.connectionProvisioning": "{{provider}} در حال اتصال است", + "newKnowledge.connectionRefreshFailed": "ما نتوانستیم این اتصال را بازخوانی کنیم. دوباره امتحان کنید.", + "newKnowledge.crawlSetupUnavailableDescription": "پیکربندی خزیدن وب‌سایت تا زمانی که گردش کار خزیدن در دسترس نباشد، غیرفعال است.", "newKnowledge.createFailed": "ما نتوانستیم این پایگاه دانش را ایجاد کنیم. دسترسی خود را بررسی کنید و دوباره امتحان کنید.", "newKnowledge.createTitle": "ایجاد دانش", "newKnowledge.creators": "ایجادکنندگان", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "به عنوان مثال خط مشی بازپرداخت، سؤالات متداول حمل و نقل، و مراحل افزایش - برای سؤالات پشتیبانی مشتری استفاده کنید", "newKnowledge.detailErrorDescription": "ما نتوانستیم این پایگاه دانش را بارگیری کنیم. دوباره امتحان کنید.", "newKnowledge.detailErrorTitle": "مشکلی پیش آمد", + "newKnowledge.disableSource": "غیر فعال کردن", "newKnowledge.discardDraftConfirm": "حذف پیش‌نویس", "newKnowledge.discardDraftDescription": "تغییرات شما در این پیش‌نویس پایگاه دانش از بین خواهد رفت.", "newKnowledge.discardDraftTitle": "این پیش‌نویس پایگاه دانش حذف شود؟", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "یک منبع را متصل کنید تا اسناد آن همگام، خودکار نمایه‌سازی و آماده استفاده بمانند؛ بدون تنظیماتی برای مدیریت. پایگاه‌های دانش قبلی شما همچنان مانند گذشته کار می‌کنند.", "newKnowledge.guideTitle": "با پایگاه دانش جدید آشنا شوید ✨", "newKnowledge.illustrationHeadline": "محتوای خود را یک‌بار متصل کنید تا هر برنامه با تازه‌ترین دانش پاسخ دهد.", + "newKnowledge.lastSyncColumn": "آخرین همگام سازی", "newKnowledge.learnMore": "بیشتر بدانید", "newKnowledge.leavePartialSetupConfirm": "خروج از راه‌اندازی", "newKnowledge.leavePartialSetupDescription": "پایگاه دانش ایجاد شد، اما مجوز آن تأیید نشد. با خروج، پایگاه دانش حفظ می‌شود؛ می‌توانید بعداً دسترسی را بررسی کنید.", "newKnowledge.leavePartialSetupTitle": "از راه‌اندازی ناتمام خارج می‌شوید؟", "newKnowledge.legacy": "قدیمی", "newKnowledge.loadMore": "بارگذاری بیشتر", + "newKnowledge.moreProviders": "بیشتر ببینید", "newKnowledge.name": "نام دانش", "newKnowledge.namePlaceholder": "به عنوان مثال راهنمای پشتیبانی مشتری", "newKnowledge.nameRequired": "یک نام پایگاه دانش وارد کنید.", "newKnowledge.new": "جدید", "newKnowledge.noDescription": "بدون توضیح", + "newKnowledge.noMatchingSources": "هیچ منبعی با این جستجو مطابقت ندارد.", "newKnowledge.notFoundDescription": "این پایگاه دانش ممکن است حذف شده باشد یا ممکن است دسترسی نداشته باشید.", "newKnowledge.notFoundTitle": "پایگاه دانش یافت نشد", + "newKnowledge.onlineDocuments": "اسناد آنلاین", + "newKnowledge.onlineDrive": "درایو آنلاین", "newKnowledge.permission": "اجازه", "newKnowledge.permissionAllMembers": "فضای کاری · همه اعضا می توانند مشاهده و ویرایش کنند", "newKnowledge.permissionOnlyMe": "فقط من", "newKnowledge.permissionRestricted": "مجوزهای فضای کاری شما اجازه تغییر این تنظیم را نمی دهد.", "newKnowledge.permissionUpdateFailed": "پایگاه دانش ایجاد شد، اما مجوز آن تأیید نشد. برای تکمیل راه‌اندازی دوباره تلاش کنید.", + "newKnowledge.providerConnected": "{{provider}} متصل شد", + "newKnowledge.providerLabel": "یک ارائه دهنده را انتخاب کنید", + "newKnowledge.providerLoadFailed": "ارائه‌دهندگان نتوانستند بارگیری کنند", + "newKnowledge.providerNotConfigured": "{{provider}} پیکربندی نشده است", + "newKnowledge.providerNotConfiguredDescription": "برای خزیدن وب‌سایت‌ها با {{provider}}، یک کلید API یا URL نقطه پایانی اضافه کنید.", + "newKnowledge.providerUnavailable": "این ارائه دهنده در دسترس نیست.", "newKnowledge.readOnlyEmpty": "از یک ویرایشگر فضای کاری بخواهید اولین پایگاه دانش را ایجاد کند.", + "newKnowledge.refreshConnectionStatus": "وضعیت بازخوانی", + "newKnowledge.refreshingConnection": "تازه‌سازی…", + "newKnowledge.removeSource": "حذف منبع", + "newKnowledge.retryProviderLoad": "دوباره امتحان کنید", "newKnowledge.routeUnavailable": "این بخش در مرحله راه اندازی بعدی در دسترس خواهد بود.", + "newKnowledge.searchSources": "منابع جستجو", + "newKnowledge.sourceActions": "اقدامات برای {{name}}", + "newKnowledge.sourceColumn": "منبع", + "newKnowledge.sourceFilterLabel": "منابع را بر اساس وضعیت فیلتر کنید", + "newKnowledge.sourceStatus.active": "فعال", + "newKnowledge.sourceStatus.disabled": "غیرفعال شد", + "newKnowledge.sourceStatus.error": "خطا", + "newKnowledge.sourceStatus.syncing": "در حال همگام سازی", + "newKnowledge.sourceSyncFailed": "ناموفق", + "newKnowledge.sourceType.connector": "برنامه متصل", + "newKnowledge.sourceType.object-storage": "درایو آنلاین", + "newKnowledge.sourceType.upload": "آپلود", + "newKnowledge.sourceType.web": "خزیدن وب سایت", + "newKnowledge.sourceTypeLabel": "نوع منبع", "newKnowledge.sources": "منابع", + "newKnowledge.sourcesDescription": "دانش از کجا می آید، چقدر تازه است و آیا آخرین همگام سازی موفق بوده است یا خیر.", + "newKnowledge.sourcesEmptyDescription": "یک وب‌سایت، فضای کاری یا درایو را متصل کنید؛ Dify آن را همگام و به‌روز نگه می‌دارد تا بازیابی هرگز مختل نشود.", + "newKnowledge.sourcesEmptyTitle": "هنوز منبعی متصل نشده است", + "newKnowledge.sourcesErrorDescription": "ما نتوانستیم منابع را بارگیری کنیم. دوباره امتحان کنید.", + "newKnowledge.sourcesErrorTitle": "منابع بارگیری نشدند", "newKnowledge.startEmpty": "شروع از خالی", "newKnowledge.startEmptyDescription": "اکنون ایجاد کنید و بعداً محتوا اضافه کنید.", "newKnowledge.startWith": "شروع کنید با", "newKnowledge.startWithHelp": "می‌توانید منابع یا اسناد بیشتری را در هر زمان اضافه کنید.", + "newKnowledge.statusColumn": "وضعیت", + "newKnowledge.syncNow": "اکنون همگام سازی کنید", + "newKnowledge.syncPolicyColumn": "خط مشی همگام سازی", "newKnowledge.tags": "برچسب‌ها", "newKnowledge.unavailableDescription": "KnowledgeFS اکنون برای این فضای کاری در دسترس نیست.", "newKnowledge.unavailableTitle": "دانش جدید در دسترس نیست", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "بارگذاری فایل‌ها", "newKnowledge.uploadFilesDescription": "فایل‌ها را از رایانه اضافه کنید — به‌محض ایجاد نمایه‌سازی می‌شوند.", "newKnowledge.viewLabel": "نمای دانش", + "newKnowledge.websiteCrawl": "خزیدن وب سایت", "noExternalKnowledge": "هنوز هیچ API دانش خارجی وجود ندارد، برای ایجاد اینجا را کلیک کنید", "parentMode.fullDoc": "مستند کامل", "parentMode.paragraph": "پاراگراف", diff --git a/web/i18n/fr-FR/dataset.json b/web/i18n/fr-FR/dataset.json index 2aeb0ee0007..554e7f76429 100644 --- a/web/i18n/fr-FR/dataset.json +++ b/web/i18n/fr-FR/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Le modèle de reclassement est nécessaire pour le mélange de bases de connaissances de haute qualité et économiques.", "mixtureInternalAndExternalTip": "Le modèle Rerank est nécessaire pour mélanger les connaissances internes et externes.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Actions", + "newKnowledge.addSource": "Ajouter une source", + "newKnowledge.addSourceDescription": "Connectez une source à cette base de connaissances : elle se synchronise automatiquement et reste à jour.", + "newKnowledge.allSources": "Toutes les sources", "newKnowledge.appsUnavailable": "— applications", + "newKnowledge.authKind.api-key": "Clé API", + "newKnowledge.authKind.endpoint": "Point de terminaison", + "newKnowledge.authenticationMethod": "Méthode d'authentification", "newKnowledge.backToList": "Retour aux bases de connaissances", + "newKnowledge.booleanFalse": "Non", + "newKnowledge.booleanTrue": "Oui", + "newKnowledge.cancelAddSource": "Annuler", "newKnowledge.cardType": "Espace de connaissances", + "newKnowledge.configureProvider": "Configurer {{provider}}", + "newKnowledge.connectProvider": "Connecter {{provider}}", "newKnowledge.connectSource": "Connecter une source", "newKnowledge.connectSourceDescription": "Le contenu reste synchronisé avec Notion, les sites web et d’autres services.", + "newKnowledge.connectingProvider": "Connexion…", + "newKnowledge.connectionFailed": "Nous n'avons pas pu connecter {{provider}}. Saisissez à nouveau les informations d'identification et réessayez.", + "newKnowledge.connectionNeedsAttention": "La connexion {{provider}} nécessite une attention particulière", + "newKnowledge.connectionNeedsAttentionDescription": "Actualisez la connexion avant d'ajouter une source de site Web.", + "newKnowledge.connectionProvisioning": "{{provider}} se connecte", + "newKnowledge.connectionRefreshFailed": "Nous n'avons pas pu actualiser cette connexion. Essayer à nouveau.", + "newKnowledge.crawlSetupUnavailableDescription": "La configuration de l'analyse du site Web est désactivée jusqu'à ce que le flux de travail d'analyse soit disponible.", "newKnowledge.createFailed": "Nous n'avons pas pu créer cette base de connaissances. Vérifiez votre accès et réessayez.", "newKnowledge.createTitle": "Créer des connaissances", "newKnowledge.creators": "Créateurs", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "par ex. Politique de remboursement, FAQ sur l'expédition et étapes de remontée d'informations – à utiliser pour les questions d'assistance client", "newKnowledge.detailErrorDescription": "Nous n'avons pas pu charger cette base de connaissances. Essayer à nouveau.", "newKnowledge.detailErrorTitle": "Quelque chose s'est mal passé", + "newKnowledge.disableSource": "Désactiver", "newKnowledge.discardDraftConfirm": "Abandonner le brouillon", "newKnowledge.discardDraftDescription": "Les modifications apportées à ce brouillon de base de connaissances seront perdues.", "newKnowledge.discardDraftTitle": "Abandonner ce brouillon de base de connaissances ?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Connectez une source et ses documents restent synchronisés, indexés automatiquement et prêts à l’emploi, sans configuration à gérer. Vos anciennes bases de connaissances continuent de fonctionner telles quelles.", "newKnowledge.guideTitle": "Découvrez la nouvelle base de connaissances ✨", "newKnowledge.illustrationHeadline": "Connectez votre contenu une fois : chaque application répond avec les connaissances les plus récentes.", + "newKnowledge.lastSyncColumn": "Dernière synchronisation", "newKnowledge.learnMore": "En savoir plus", "newKnowledge.leavePartialSetupConfirm": "Quitter la configuration", "newKnowledge.leavePartialSetupDescription": "La base de connaissances a été créée, mais son autorisation n’a pas pu être confirmée. Si vous quittez, la base de connaissances sera conservée ; vous pourrez vérifier l’accès plus tard.", "newKnowledge.leavePartialSetupTitle": "Quitter la configuration incomplète ?", "newKnowledge.legacy": "Ancien", "newKnowledge.loadMore": "Charger plus", + "newKnowledge.moreProviders": "Voir plus", "newKnowledge.name": "Nom de la connaissance", "newKnowledge.namePlaceholder": "par ex. Manuel de support client", "newKnowledge.nameRequired": "Entrez un nom de base de connaissances.", "newKnowledge.new": "Nouveau", "newKnowledge.noDescription": "Aucune description", + "newKnowledge.noMatchingSources": "Aucune source ne correspond à cette recherche.", "newKnowledge.notFoundDescription": "Cette base de connaissances a peut-être été supprimée ou vous n'y avez peut-être pas accès.", "newKnowledge.notFoundTitle": "Base de connaissances introuvable", + "newKnowledge.onlineDocuments": "Documents en ligne", + "newKnowledge.onlineDrive": "Drive en ligne", "newKnowledge.permission": "Autorisation", "newKnowledge.permissionAllMembers": "Espace de travail · tous les membres peuvent consulter et modifier", "newKnowledge.permissionOnlyMe": "Seulement moi", "newKnowledge.permissionRestricted": "Les autorisations de votre espace de travail ne permettent pas de modifier ce paramètre.", "newKnowledge.permissionUpdateFailed": "La base de connaissances a été créée, mais son autorisation n’a pas pu être confirmée. Réessayez pour terminer la configuration.", + "newKnowledge.providerConnected": "{{provider}} connecté", + "newKnowledge.providerLabel": "Sélectionnez un fournisseur", + "newKnowledge.providerLoadFailed": "Les fournisseurs n'ont pas pu charger", + "newKnowledge.providerNotConfigured": "{{provider}} n'est pas configuré", + "newKnowledge.providerNotConfiguredDescription": "Ajoutez une clé API ou une URL de point de terminaison pour explorer les sites Web avec {{provider}}.", + "newKnowledge.providerUnavailable": "Ce fournisseur n'est pas disponible.", "newKnowledge.readOnlyEmpty": "Demandez à un éditeur de l’espace de travail de créer la première base de connaissances.", + "newKnowledge.refreshConnectionStatus": "Actualiser l'état", + "newKnowledge.refreshingConnection": "Rafraîchissant…", + "newKnowledge.removeSource": "Supprimer la source", + "newKnowledge.retryProviderLoad": "Réessayer", "newKnowledge.routeUnavailable": "Cette section deviendra disponible lors de la prochaine étape de configuration.", + "newKnowledge.searchSources": "Sources de recherche", + "newKnowledge.sourceActions": "Actions pour {{name}}", + "newKnowledge.sourceColumn": "Origine", + "newKnowledge.sourceFilterLabel": "Filtrer les sources par statut", + "newKnowledge.sourceStatus.active": "Actif", + "newKnowledge.sourceStatus.disabled": "Désactivé", + "newKnowledge.sourceStatus.error": "Erreur", + "newKnowledge.sourceStatus.syncing": "Synchronisation", + "newKnowledge.sourceSyncFailed": "Échec", + "newKnowledge.sourceType.connector": "Application connectée", + "newKnowledge.sourceType.object-storage": "Lecteur en ligne", + "newKnowledge.sourceType.upload": "Télécharger", + "newKnowledge.sourceType.web": "Exploration du site Web", + "newKnowledge.sourceTypeLabel": "Type de source", "newKnowledge.sources": "Sources", + "newKnowledge.sourcesDescription": "D'où vient la connaissance, à quel point elle est fraîche et si la dernière synchronisation a réussi.", + "newKnowledge.sourcesEmptyDescription": "Connectez un site Web, un espace de travail ou un lecteur — Dify le maintient synchronisé et à jour afin que la récupération ne soit jamais interrompue.", + "newKnowledge.sourcesEmptyTitle": "Aucune source connectée pour le moment", + "newKnowledge.sourcesErrorDescription": "Nous n'avons pas pu charger les sources. Essayer à nouveau.", + "newKnowledge.sourcesErrorTitle": "Les sources n'ont pas pu être chargées", "newKnowledge.startEmpty": "Commencer à vide", "newKnowledge.startEmptyDescription": "Créez-la maintenant et ajoutez du contenu plus tard.", "newKnowledge.startWith": "Commencez par", "newKnowledge.startWithHelp": "Vous pouvez ajouter plus de sources ou de documents à tout moment.", + "newKnowledge.statusColumn": "Statut", + "newKnowledge.syncNow": "Synchroniser maintenant", + "newKnowledge.syncPolicyColumn": "Politique de synchronisation", "newKnowledge.tags": "Étiquettes", "newKnowledge.unavailableDescription": "KnowledgeFS n’est pas disponible pour cet espace de travail actuellement.", "newKnowledge.unavailableTitle": "Les nouvelles connaissances sont indisponibles", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Importer des fichiers", "newKnowledge.uploadFilesDescription": "Ajoutez des fichiers depuis votre ordinateur : ils sont indexés dès leur création.", "newKnowledge.viewLabel": "Vue des connaissances", + "newKnowledge.websiteCrawl": "Exploration du site Web", "noExternalKnowledge": "Il n’y a pas encore d’API de connaissances externes, cliquez ici pour créer", "parentMode.fullDoc": "Doc complet", "parentMode.paragraph": "Paragraphe", diff --git a/web/i18n/hi-IN/dataset.json b/web/i18n/hi-IN/dataset.json index 8af2d5d883f..be9dad31b60 100644 --- a/web/i18n/hi-IN/dataset.json +++ b/web/i18n/hi-IN/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "उच्च गुणवत्ता और किफायती ज्ञान आधारों के मिश्रण के लिए पुनः रैंकिंग मॉडल आवश्यक है।", "mixtureInternalAndExternalTip": "आंतरिक और बाहरी ज्ञान के मिश्रण के लिए रीरैंक मॉडल की आवश्यकता होती है।", "multimodal": "बहु-मोडल", + "newKnowledge.actionsColumn": "क्रियाएँ", + "newKnowledge.addSource": "स्रोत जोड़ें", + "newKnowledge.addSourceDescription": "इस ज्ञानकोष से एक स्रोत कनेक्ट करें - यह स्वचालित रूप से समन्वयित होता है और ताज़ा रहता है।", + "newKnowledge.allSources": "सभी स्रोत", "newKnowledge.appsUnavailable": "— ऐप", + "newKnowledge.authKind.api-key": "एपीआई कुंजी", + "newKnowledge.authKind.endpoint": "समापन बिंदु", + "newKnowledge.authenticationMethod": "प्रमाणीकरण विधि", "newKnowledge.backToList": "ज्ञानकोष पर वापस जाएँ", + "newKnowledge.booleanFalse": "नहीं", + "newKnowledge.booleanTrue": "हाँ", + "newKnowledge.cancelAddSource": "रद्द करें", "newKnowledge.cardType": "नॉलेज स्पेस", + "newKnowledge.configureProvider": "{{provider}} कॉन्फ़िगर करें", + "newKnowledge.connectProvider": "{{provider}} कनेक्ट करें", "newKnowledge.connectSource": "स्रोत कनेक्ट करें", "newKnowledge.connectSourceDescription": "कंटेंट Notion, वेबसाइटों और अन्य सेवाओं के साथ सिंक रहता है।", + "newKnowledge.connectingProvider": "कनेक्ट हो रहा है...", + "newKnowledge.connectionFailed": "हम {{provider}} को कनेक्ट नहीं कर सके। क्रेडेंशियल पुनः दर्ज करें और पुनः प्रयास करें।", + "newKnowledge.connectionNeedsAttention": "{{provider}} कनेक्शन पर ध्यान देने की जरूरत है", + "newKnowledge.connectionNeedsAttentionDescription": "वेबसाइट स्रोत जोड़ने से पहले कनेक्शन को ताज़ा करें।", + "newKnowledge.connectionProvisioning": "{{provider}} कनेक्ट हो रहा है", + "newKnowledge.connectionRefreshFailed": "हम इस कनेक्शन को ताज़ा नहीं कर सके। पुनः प्रयास करें।", + "newKnowledge.crawlSetupUnavailableDescription": "क्रॉल वर्कफ़्लो उपलब्ध होने तक वेबसाइट क्रॉल कॉन्फ़िगरेशन अक्षम है।", "newKnowledge.createFailed": "हम यह ज्ञानकोष नहीं बना सके। अपनी पहुंच जांचें और पुनः प्रयास करें।", "newKnowledge.createTitle": "ज्ञान पैदा करें", "newKnowledge.creators": "निर्माता", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "जैसे रिफंड नीति, शिपिंग एफएक्यू और एस्केलेशन चरण - ग्राहक सहायता प्रश्नों के लिए उपयोग करें", "newKnowledge.detailErrorDescription": "हम इस ज्ञानकोष को लोड नहीं कर सके. पुनः प्रयास करें।", "newKnowledge.detailErrorTitle": "कुछ ग़लत हो गया", + "newKnowledge.disableSource": "अक्षम करें", "newKnowledge.discardDraftConfirm": "ड्राफ़्ट हटाएँ", "newKnowledge.discardDraftDescription": "इस नॉलेज बेस ड्राफ़्ट में किए गए आपके बदलाव खो जाएँगे।", "newKnowledge.discardDraftTitle": "क्या यह नॉलेज बेस ड्राफ़्ट हटाना है?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "किसी स्रोत को कनेक्ट करें और उसके दस्तावेज़ सिंक, अपने-आप इंडेक्स और उपयोग के लिए तैयार रहेंगे—किसी सेटअप को संभालने की ज़रूरत नहीं। आपके पुराने नॉलेज बेस पहले की तरह काम करते रहेंगे।", "newKnowledge.guideTitle": "नए नॉलेज बेस से मिलें ✨", "newKnowledge.illustrationHeadline": "अपनी सामग्री एक बार कनेक्ट करें — हर ऐप नवीनतम ज्ञान के साथ जवाब देगा।", + "newKnowledge.lastSyncColumn": "अंतिम सिंक", "newKnowledge.learnMore": "और जानें", "newKnowledge.leavePartialSetupConfirm": "सेटअप छोड़ें", "newKnowledge.leavePartialSetupDescription": "नॉलेज बेस बन गया है, लेकिन उसकी अनुमति की पुष्टि नहीं हो सकी। छोड़ने पर नॉलेज बेस बना रहेगा; आप बाद में एक्सेस की समीक्षा कर सकते हैं।", "newKnowledge.leavePartialSetupTitle": "क्या अधूरा सेटअप छोड़ना है?", "newKnowledge.legacy": "पुराना", "newKnowledge.loadMore": "और लोड करें", + "newKnowledge.moreProviders": "और देखें", "newKnowledge.name": "ज्ञान नाम", "newKnowledge.namePlaceholder": "जैसे ग्राहक सहायता पुस्तिका", "newKnowledge.nameRequired": "नॉलेज बेस नाम दर्ज करें.", "newKnowledge.new": "नया", "newKnowledge.noDescription": "कोई विवरण नहीं", + "newKnowledge.noMatchingSources": "इस खोज से कोई स्रोत मेल नहीं खाता।", "newKnowledge.notFoundDescription": "हो सकता है कि यह ज्ञानकोष हटा दिया गया हो या आपके पास पहुंच न हो।", "newKnowledge.notFoundTitle": "ज्ञान का आधार नहीं मिला", + "newKnowledge.onlineDocuments": "ऑनलाइन दस्तावेज़", + "newKnowledge.onlineDrive": "ऑनलाइन ड्राइव", "newKnowledge.permission": "अनुमति", "newKnowledge.permissionAllMembers": "कार्यक्षेत्र · सभी सदस्य देख और संपादित कर सकते हैं", "newKnowledge.permissionOnlyMe": "केवल मैं", "newKnowledge.permissionRestricted": "आपकी कार्यस्थान अनुमतियाँ इस सेटिंग को बदलने की अनुमति नहीं देतीं।", "newKnowledge.permissionUpdateFailed": "नॉलेज बेस बन गया है, लेकिन उसकी अनुमति की पुष्टि नहीं हो सकी। सेटअप पूरा करने के लिए फिर से कोशिश करें।", + "newKnowledge.providerConnected": "{{provider}} जुड़ा", + "newKnowledge.providerLabel": "एक प्रदाता का चयन करें", + "newKnowledge.providerLoadFailed": "प्रदाता लोड नहीं कर सके", + "newKnowledge.providerNotConfigured": "{{provider}} कॉन्फ़िगर नहीं है", + "newKnowledge.providerNotConfiguredDescription": "{{provider}} के साथ वेबसाइटों को क्रॉल करने के लिए एक एपीआई कुंजी या एंडपॉइंट यूआरएल जोड़ें।", + "newKnowledge.providerUnavailable": "यह प्रदाता अनुपलब्ध है।", "newKnowledge.readOnlyEmpty": "पहला नॉलेज बेस बनाने के लिए कार्यस्थान संपादक से कहें।", + "newKnowledge.refreshConnectionStatus": "स्थिति ताज़ा करें", + "newKnowledge.refreshingConnection": "ताज़ा…", + "newKnowledge.removeSource": "स्रोत हटाएं", + "newKnowledge.retryProviderLoad": "पुनः प्रयास करें", "newKnowledge.routeUnavailable": "यह अनुभाग अगले सेटअप चरण में उपलब्ध हो जाएगा.", + "newKnowledge.searchSources": "स्रोत खोजें", + "newKnowledge.sourceActions": "{{name}} के लिए कार्रवाइयां", + "newKnowledge.sourceColumn": "स्रोत", + "newKnowledge.sourceFilterLabel": "स्थिति के अनुसार स्रोतों को फ़िल्टर करें", + "newKnowledge.sourceStatus.active": "सक्रिय", + "newKnowledge.sourceStatus.disabled": "विकलांग", + "newKnowledge.sourceStatus.error": "त्रुटि", + "newKnowledge.sourceStatus.syncing": "सिंक हो रहा है", + "newKnowledge.sourceSyncFailed": "विफल", + "newKnowledge.sourceType.connector": "कनेक्टेड ऐप", + "newKnowledge.sourceType.object-storage": "ऑनलाइन ड्राइव", + "newKnowledge.sourceType.upload": "अपलोड करें", + "newKnowledge.sourceType.web": "वेबसाइट क्रॉल", + "newKnowledge.sourceTypeLabel": "स्रोत प्रकार", "newKnowledge.sources": "सूत्र", + "newKnowledge.sourcesDescription": "ज्ञान कहां से आता है, यह कितना ताज़ा है, और क्या अंतिम सिंक सफल हुआ।", + "newKnowledge.sourcesEmptyDescription": "वेबसाइट, वर्कस्पेस या ड्राइव कनेक्ट करें — Dify इसे सिंक और अपडेट रखता है, ताकि पुनर्प्राप्ति कभी बाधित न हो।", + "newKnowledge.sourcesEmptyTitle": "अभी तक कोई स्रोत नहीं जुड़ा है", + "newKnowledge.sourcesErrorDescription": "हम स्रोत लोड नहीं कर सके। पुनः प्रयास करें।", + "newKnowledge.sourcesErrorTitle": "स्रोत लोड नहीं हो सके", "newKnowledge.startEmpty": "खाली शुरू करें", "newKnowledge.startEmptyDescription": "अभी बनाएँ, कंटेंट बाद में जोड़ें।", "newKnowledge.startWith": "से शुरू करें", "newKnowledge.startWithHelp": "आप किसी भी समय अधिक स्रोत या दस्तावेज़ जोड़ सकते हैं।", + "newKnowledge.statusColumn": "स्थिति", + "newKnowledge.syncNow": "अभी सिंक करें", + "newKnowledge.syncPolicyColumn": "सिंक नीति", "newKnowledge.tags": "टैग", "newKnowledge.unavailableDescription": "KnowledgeFS अभी इस कार्यस्थान के लिए उपलब्ध नहीं है।", "newKnowledge.unavailableTitle": "नया नॉलेज उपलब्ध नहीं है", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "फ़ाइलें अपलोड करें", "newKnowledge.uploadFilesDescription": "अपने कंप्यूटर से फ़ाइलें जोड़ें — बनाते ही वे इंडेक्स हो जाएँगी।", "newKnowledge.viewLabel": "नॉलेज दृश्य", + "newKnowledge.websiteCrawl": "वेबसाइट क्रॉल", "noExternalKnowledge": "अभी तक कोई बाहरी ज्ञान एपीआई नहीं है, बनाने के लिए यहां क्लिक करें", "parentMode.fullDoc": "पूर्ण-दस्तावेज़", "parentMode.paragraph": "अनुच्‍छेद", diff --git a/web/i18n/id-ID/dataset.json b/web/i18n/id-ID/dataset.json index be3ff3a4934..42420ef29d1 100644 --- a/web/i18n/id-ID/dataset.json +++ b/web/i18n/id-ID/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Model Rerank diperlukan untuk campuran basis pengetahuan berkualitas tinggi dan ekonomis.", "mixtureInternalAndExternalTip": "Model Rerank diperlukan untuk campuran pengetahuan internal dan eksternal.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Tindakan", + "newKnowledge.addSource": "Tambahkan sumber", + "newKnowledge.addSourceDescription": "Hubungkan sumber ke basis pengetahuan ini — sumber tersebut akan disinkronkan secara otomatis dan tetap segar.", + "newKnowledge.allSources": "Semua sumber", "newKnowledge.appsUnavailable": "— aplikasi", + "newKnowledge.authKind.api-key": "kunci API", + "newKnowledge.authKind.endpoint": "Titik akhir", + "newKnowledge.authenticationMethod": "Metode otentikasi", "newKnowledge.backToList": "Kembali ke basis pengetahuan", + "newKnowledge.booleanFalse": "Tidak", + "newKnowledge.booleanTrue": "Ya", + "newKnowledge.cancelAddSource": "Batal", "newKnowledge.cardType": "Ruang pengetahuan", + "newKnowledge.configureProvider": "Konfigurasikan {{provider}}", + "newKnowledge.connectProvider": "Hubungkan {{provider}}", "newKnowledge.connectSource": "Hubungkan sumber", "newKnowledge.connectSourceDescription": "Konten tetap tersinkronisasi dengan Notion, situs web, dan layanan lainnya.", + "newKnowledge.connectingProvider": "Menghubungkan…", + "newKnowledge.connectionFailed": "Kami tidak dapat menghubungkan {{provider}}. Masukkan kembali kredensial dan coba lagi.", + "newKnowledge.connectionNeedsAttention": "Koneksi {{provider}} perlu diperhatikan", + "newKnowledge.connectionNeedsAttentionDescription": "Segarkan koneksi sebelum menambahkan sumber situs web.", + "newKnowledge.connectionProvisioning": "{{provider}} terhubung", + "newKnowledge.connectionRefreshFailed": "Kami tidak dapat menyegarkan koneksi ini. Coba lagi.", + "newKnowledge.crawlSetupUnavailableDescription": "Konfigurasi perayapan situs web dinonaktifkan hingga alur kerja perayapan tersedia.", "newKnowledge.createFailed": "Kami tidak dapat membuat basis pengetahuan ini. Periksa akses Anda dan coba lagi.", "newKnowledge.createTitle": "Ciptakan Pengetahuan", "newKnowledge.creators": "Pembuat", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "misalnya Kebijakan pengembalian dana, FAQ pengiriman, dan langkah eskalasi — digunakan untuk pertanyaan dukungan pelanggan", "newKnowledge.detailErrorDescription": "Kami tidak dapat memuat basis pengetahuan ini. Coba lagi.", "newKnowledge.detailErrorTitle": "Ada yang tidak beres", + "newKnowledge.disableSource": "Nonaktifkan", "newKnowledge.discardDraftConfirm": "Buang draf", "newKnowledge.discardDraftDescription": "Perubahan pada draf basis pengetahuan ini akan hilang.", "newKnowledge.discardDraftTitle": "Buang draf basis pengetahuan ini?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Hubungkan sumber dan dokumennya akan tetap tersinkronisasi, diindeks otomatis, serta siap digunakan tanpa pengaturan yang perlu dikelola. Basis pengetahuan lama Anda tetap berfungsi seperti biasa.", "newKnowledge.guideTitle": "Kenali Basis Pengetahuan baru ✨", "newKnowledge.illustrationHeadline": "Hubungkan konten Anda sekali — setiap aplikasi menjawab dengan pengetahuan terbaru.", + "newKnowledge.lastSyncColumn": "Sinkronisasi terakhir", "newKnowledge.learnMore": "Pelajari lebih lanjut", "newKnowledge.leavePartialSetupConfirm": "Keluar dari penyiapan", "newKnowledge.leavePartialSetupDescription": "Basis pengetahuan telah dibuat, tetapi izinnya tidak dapat dikonfirmasi. Jika keluar, basis pengetahuan akan tetap tersimpan; Anda dapat meninjau akses nanti.", "newKnowledge.leavePartialSetupTitle": "Keluar dari penyiapan yang belum selesai?", "newKnowledge.legacy": "Lama", "newKnowledge.loadMore": "Muat lebih banyak", + "newKnowledge.moreProviders": "Lihat lebih banyak", "newKnowledge.name": "Nama pengetahuan", "newKnowledge.namePlaceholder": "misalnya Buku Pegangan Dukungan Pelanggan", "newKnowledge.nameRequired": "Masukkan nama basis pengetahuan.", "newKnowledge.new": "Baru", "newKnowledge.noDescription": "Tidak ada deskripsi", + "newKnowledge.noMatchingSources": "Tidak ada sumber yang cocok dengan pencarian ini.", "newKnowledge.notFoundDescription": "Basis pengetahuan ini mungkin telah dihapus atau Anda mungkin tidak memiliki akses.", "newKnowledge.notFoundTitle": "Basis pengetahuan tidak ditemukan", + "newKnowledge.onlineDocuments": "Dokumen daring", + "newKnowledge.onlineDrive": "Perjalanan daring", "newKnowledge.permission": "Izin", "newKnowledge.permissionAllMembers": "Ruang Kerja · semua anggota dapat melihat dan mengedit", "newKnowledge.permissionOnlyMe": "Hanya aku", "newKnowledge.permissionRestricted": "Izin ruang kerja Anda tidak mengizinkan perubahan pengaturan ini.", "newKnowledge.permissionUpdateFailed": "Basis pengetahuan telah dibuat, tetapi izinnya tidak dapat dikonfirmasi. Coba lagi untuk menyelesaikan penyiapan.", + "newKnowledge.providerConnected": "{{provider}} terhubung", + "newKnowledge.providerLabel": "Pilih penyedia", + "newKnowledge.providerLoadFailed": "Penyedia tidak dapat memuat", + "newKnowledge.providerNotConfigured": "{{provider}} tidak dikonfigurasi", + "newKnowledge.providerNotConfiguredDescription": "Tambahkan kunci API atau URL titik akhir untuk merayapi situs web dengan {{provider}}.", + "newKnowledge.providerUnavailable": "Penyedia ini tidak tersedia.", "newKnowledge.readOnlyEmpty": "Minta editor ruang kerja membuat basis pengetahuan pertama.", + "newKnowledge.refreshConnectionStatus": "Segarkan status", + "newKnowledge.refreshingConnection": "Menyegarkan…", + "newKnowledge.removeSource": "Hapus sumber", + "newKnowledge.retryProviderLoad": "Coba lagi", "newKnowledge.routeUnavailable": "Bagian ini akan tersedia pada langkah penyiapan berikutnya.", + "newKnowledge.searchSources": "Cari sumber", + "newKnowledge.sourceActions": "Tindakan untuk {{name}}", + "newKnowledge.sourceColumn": "Sumber", + "newKnowledge.sourceFilterLabel": "Filter sumber berdasarkan status", + "newKnowledge.sourceStatus.active": "Aktif", + "newKnowledge.sourceStatus.disabled": "Dinonaktifkan", + "newKnowledge.sourceStatus.error": "Kesalahan", + "newKnowledge.sourceStatus.syncing": "Sinkronisasi", + "newKnowledge.sourceSyncFailed": "Gagal", + "newKnowledge.sourceType.connector": "Aplikasi terhubung", + "newKnowledge.sourceType.object-storage": "Perjalanan daring", + "newKnowledge.sourceType.upload": "Unggah", + "newKnowledge.sourceType.web": "Perayapan situs web", + "newKnowledge.sourceTypeLabel": "Jenis sumber", "newKnowledge.sources": "Sumber", + "newKnowledge.sourcesDescription": "Dari mana pengetahuan berasal, seberapa segar pengetahuan tersebut, dan apakah sinkronisasi terakhir berhasil.", + "newKnowledge.sourcesEmptyDescription": "Hubungkan situs web, ruang kerja, atau drive — Dify menjaganya tetap sinkron dan terbaru agar pengambilan tidak pernah terganggu.", + "newKnowledge.sourcesEmptyTitle": "Belum ada sumber yang terhubung", + "newKnowledge.sourcesErrorDescription": "Kami tidak dapat memuat sumber. Coba lagi.", + "newKnowledge.sourcesErrorTitle": "Sumber tidak dapat dimuat", "newKnowledge.startEmpty": "Mulai kosong", "newKnowledge.startEmptyDescription": "Buat sekarang, tambahkan konten nanti.", "newKnowledge.startWith": "Mulailah dengan", "newKnowledge.startWithHelp": "Anda dapat menambahkan lebih banyak Sumber atau Dokumen kapan saja.", + "newKnowledge.statusColumn": "Status", + "newKnowledge.syncNow": "Sinkronkan sekarang", + "newKnowledge.syncPolicyColumn": "Kebijakan sinkronisasi", "newKnowledge.tags": "Tag", "newKnowledge.unavailableDescription": "KnowledgeFS saat ini tidak tersedia untuk ruang kerja ini.", "newKnowledge.unavailableTitle": "Pengetahuan Baru tidak tersedia", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Unggah file", "newKnowledge.uploadFilesDescription": "Tambahkan file dari komputer — file akan diindeks segera setelah dibuat.", "newKnowledge.viewLabel": "Tampilan pengetahuan", + "newKnowledge.websiteCrawl": "Perayapan situs web", "noExternalKnowledge": "Belum ada API Pengetahuan Eksternal, klik di sini untuk membuat", "parentMode.fullDoc": "Dokumen lengkap", "parentMode.paragraph": "Paragraf", diff --git a/web/i18n/it-IT/dataset.json b/web/i18n/it-IT/dataset.json index f6ccd66f909..0add8ddd534 100644 --- a/web/i18n/it-IT/dataset.json +++ b/web/i18n/it-IT/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Il modello di riclassificazione è necessario per la miscela di basi di conoscenza di alta qualità ed economiche.", "mixtureInternalAndExternalTip": "Il modello Rerank è necessario per la combinazione di conoscenze interne ed esterne.", "multimodal": "Multimodale", + "newKnowledge.actionsColumn": "Azioni", + "newKnowledge.addSource": "Aggiungi fonte", + "newKnowledge.addSourceDescription": "Collega una fonte a questa knowledge base: si sincronizza automaticamente e rimane aggiornata.", + "newKnowledge.allSources": "Tutte le fonti", "newKnowledge.appsUnavailable": "— app", + "newKnowledge.authKind.api-key": "Chiave API", + "newKnowledge.authKind.endpoint": "Punto finale", + "newKnowledge.authenticationMethod": "Metodo di autenticazione", "newKnowledge.backToList": "Torniamo alle basi di conoscenza", + "newKnowledge.booleanFalse": "No", + "newKnowledge.booleanTrue": "Sì", + "newKnowledge.cancelAddSource": "Annulla", "newKnowledge.cardType": "Spazio di conoscenza", + "newKnowledge.configureProvider": "Configura {{provider}}", + "newKnowledge.connectProvider": "Connetti {{provider}}", "newKnowledge.connectSource": "Collega una fonte", "newKnowledge.connectSourceDescription": "I contenuti restano sincronizzati con Notion, siti web e altri servizi.", + "newKnowledge.connectingProvider": "Connessione…", + "newKnowledge.connectionFailed": "Impossibile connettere {{provider}}. Reinserire le credenziali e riprovare.", + "newKnowledge.connectionNeedsAttention": "La connessione {{provider}} richiede attenzione", + "newKnowledge.connectionNeedsAttentionDescription": "Aggiorna la connessione prima di aggiungere una fonte web.", + "newKnowledge.connectionProvisioning": "{{provider}} si sta connettendo", + "newKnowledge.connectionRefreshFailed": "Impossibile aggiornare questa connessione. Riprova.", + "newKnowledge.crawlSetupUnavailableDescription": "La configurazione della scansione del sito web è disabilitata finché il flusso di lavoro di scansione non è disponibile.", "newKnowledge.createFailed": "Non è stato possibile creare questa base di conoscenza. Controlla il tuo accesso e riprova.", "newKnowledge.createTitle": "Creare Conoscenza", "newKnowledge.creators": "Autori", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "per esempio. Politica di rimborso, domande frequenti sulla spedizione e passaggi di escalation: utilizzali per domande sull'assistenza clienti", "newKnowledge.detailErrorDescription": "Impossibile caricare questa knowledge base. Riprova.", "newKnowledge.detailErrorTitle": "Qualcosa è andato storto", + "newKnowledge.disableSource": "Disabilita", "newKnowledge.discardDraftConfirm": "Scarta bozza", "newKnowledge.discardDraftDescription": "Le modifiche a questa bozza della knowledge base andranno perse.", "newKnowledge.discardDraftTitle": "Scartare questa bozza della knowledge base?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Collega una fonte e i suoi documenti resteranno sincronizzati, indicizzati automaticamente e pronti all’uso, senza nulla da gestire. Le knowledge base precedenti continueranno a funzionare come prima.", "newKnowledge.guideTitle": "Scopri la nuova Knowledge Base ✨", "newKnowledge.illustrationHeadline": "Collega i tuoi contenuti una sola volta: ogni app risponderà con le conoscenze più aggiornate.", + "newKnowledge.lastSyncColumn": "Ultima sincronizzazione", "newKnowledge.learnMore": "Scopri di più", "newKnowledge.leavePartialSetupConfirm": "Esci dalla configurazione", "newKnowledge.leavePartialSetupDescription": "La knowledge base è stata creata, ma non è stato possibile confermarne l’autorizzazione. Uscendo, la knowledge base verrà mantenuta; potrai verificare l’accesso in seguito.", "newKnowledge.leavePartialSetupTitle": "Uscire dalla configurazione incompleta?", "newKnowledge.legacy": "Legacy", "newKnowledge.loadMore": "Carica altro", + "newKnowledge.moreProviders": "Vedi di più", "newKnowledge.name": "Nome della conoscenza", "newKnowledge.namePlaceholder": "ad es. Manuale dell'assistenza clienti", "newKnowledge.nameRequired": "Inserisci un nome per la knowledge base.", "newKnowledge.new": "Nuovo", "newKnowledge.noDescription": "Nessuna descrizione", + "newKnowledge.noMatchingSources": "Nessuna fonte corrisponde a questa ricerca.", "newKnowledge.notFoundDescription": "Questa knowledge base potrebbe essere stata eliminata o potresti non avere accesso.", "newKnowledge.notFoundTitle": "Base di conoscenza non trovata", + "newKnowledge.onlineDocuments": "Documenti online", + "newKnowledge.onlineDrive": "Unità in linea", "newKnowledge.permission": "Autorizzazione", "newKnowledge.permissionAllMembers": "Area di lavoro · tutti i membri possono visualizzare e modificare", "newKnowledge.permissionOnlyMe": "Solo io", "newKnowledge.permissionRestricted": "Le autorizzazioni dell'area di lavoro non consentono di modificare questa impostazione.", "newKnowledge.permissionUpdateFailed": "La knowledge base è stata creata, ma non è stato possibile confermarne l’autorizzazione. Riprova per completare la configurazione.", + "newKnowledge.providerConnected": "{{provider}} connesso", + "newKnowledge.providerLabel": "Seleziona un fornitore", + "newKnowledge.providerLoadFailed": "Impossibile caricare i provider", + "newKnowledge.providerNotConfigured": "{{provider}} non è configurato", + "newKnowledge.providerNotConfiguredDescription": "Aggiungi una chiave API o un URL endpoint per eseguire la scansione dei siti web con {{provider}}.", + "newKnowledge.providerUnavailable": "Questo fornitore non è disponibile.", "newKnowledge.readOnlyEmpty": "Chiedi a un editor dello spazio di lavoro di creare la prima knowledge base.", + "newKnowledge.refreshConnectionStatus": "Aggiorna lo stato", + "newKnowledge.refreshingConnection": "Aggiornamento…", + "newKnowledge.removeSource": "Rimuovi la fonte", + "newKnowledge.retryProviderLoad": "Riprova", "newKnowledge.routeUnavailable": "Questa sezione diventerà disponibile nella fase di configurazione successiva.", + "newKnowledge.searchSources": "Cerca fonti", + "newKnowledge.sourceActions": "Azioni per {{name}}", + "newKnowledge.sourceColumn": "Fonte", + "newKnowledge.sourceFilterLabel": "Filtra le fonti per stato", + "newKnowledge.sourceStatus.active": "Attivo", + "newKnowledge.sourceStatus.disabled": "Disabilitato", + "newKnowledge.sourceStatus.error": "Errore", + "newKnowledge.sourceStatus.syncing": "Sincronizzazione", + "newKnowledge.sourceSyncFailed": "Non riuscito", + "newKnowledge.sourceType.connector": "Applicazione connessa", + "newKnowledge.sourceType.object-storage": "Unità in linea", + "newKnowledge.sourceType.upload": "Carica", + "newKnowledge.sourceType.web": "Scansione del sito web", + "newKnowledge.sourceTypeLabel": "Tipo di origine", "newKnowledge.sources": "Fonti", + "newKnowledge.sourcesDescription": "Da dove proviene la conoscenza, quanto è recente e se l'ultima sincronizzazione è riuscita.", + "newKnowledge.sourcesEmptyDescription": "Collega un sito web, uno spazio di lavoro o un'unità: Dify lo mantiene sincronizzato e aggiornato, così il recupero non si interrompe mai.", + "newKnowledge.sourcesEmptyTitle": "Nessuna sorgente ancora collegata", + "newKnowledge.sourcesErrorDescription": "Impossibile caricare i sorgenti. Riprova.", + "newKnowledge.sourcesErrorTitle": "Impossibile caricare le fonti", "newKnowledge.startEmpty": "Inizia da zero", "newKnowledge.startEmptyDescription": "Creala ora e aggiungi i contenuti in seguito.", "newKnowledge.startWith": "Inizia con", "newKnowledge.startWithHelp": "Puoi aggiungere più fonti o documenti in qualsiasi momento.", + "newKnowledge.statusColumn": "Stato", + "newKnowledge.syncNow": "Sincronizza ora", + "newKnowledge.syncPolicyColumn": "Criterio di sincronizzazione", "newKnowledge.tags": "Tag", "newKnowledge.unavailableDescription": "KnowledgeFS non è al momento disponibile per questo spazio di lavoro.", "newKnowledge.unavailableTitle": "La nuova conoscenza non è disponibile", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Carica file", "newKnowledge.uploadFilesDescription": "Aggiungi file dal computer: vengono indicizzati appena li crei.", "newKnowledge.viewLabel": "Vista conoscenza", + "newKnowledge.websiteCrawl": "Scansione del sito web", "noExternalKnowledge": "Non esiste ancora un'API di conoscenza esterna, fai clic qui per creare", "parentMode.fullDoc": "Full-doc", "parentMode.paragraph": "Paragrafo", diff --git a/web/i18n/ja-JP/dataset.json b/web/i18n/ja-JP/dataset.json index 325cd6eb412..9ed96ed01e7 100644 --- a/web/i18n/ja-JP/dataset.json +++ b/web/i18n/ja-JP/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "高品質なナレッジベースとコスト重視のナレッジベースを混在させるには、Rerank モデルが必要です。", "mixtureInternalAndExternalTip": "内部と外部のナレッジベースを混在させる場合、Rerank モデルが必要です。", "multimodal": "マルチモーダル", + "newKnowledge.actionsColumn": "アクション", + "newKnowledge.addSource": "ソースを追加", + "newKnowledge.addSourceDescription": "ソースをこのナレッジ ベースに接続すると、自動的に同期され、最新の状態が保たれます。", + "newKnowledge.allSources": "すべてのソース", "newKnowledge.appsUnavailable": "— 個のアプリ", + "newKnowledge.authKind.api-key": "APIキー", + "newKnowledge.authKind.endpoint": "エンドポイント", + "newKnowledge.authenticationMethod": "認証方法", "newKnowledge.backToList": "ナレッジベースに戻る", + "newKnowledge.booleanFalse": "いいえ", + "newKnowledge.booleanTrue": "はい", + "newKnowledge.cancelAddSource": "キャンセル", "newKnowledge.cardType": "ナレッジスペース", + "newKnowledge.configureProvider": "{{provider}} を構成する", + "newKnowledge.connectProvider": "{{provider}} を接続する", "newKnowledge.connectSource": "ソースを接続", "newKnowledge.connectSourceDescription": "コンテンツは Notion、Web サイト、その他のサービスと同期され続けます。", + "newKnowledge.connectingProvider": "接続中…", + "newKnowledge.connectionFailed": "{{provider}} に接続できませんでした。資格情報を再入力して、再試行してください。", + "newKnowledge.connectionNeedsAttention": "{{provider}} 接続には注意が必要です", + "newKnowledge.connectionNeedsAttentionDescription": "Web サイトのソースを追加する前に接続を更新してください。", + "newKnowledge.connectionProvisioning": "{{provider}} が接続中です", + "newKnowledge.connectionRefreshFailed": "この接続を更新できませんでした。もう一度やり直してください。", + "newKnowledge.crawlSetupUnavailableDescription": "Web サイトのクロール設定は、クロール ワークフローが利用可能になるまで無効になります。", "newKnowledge.createFailed": "このナレッジ ベースを作成できませんでした。アクセスを確認して再試行してください。", "newKnowledge.createTitle": "知識の創造", "newKnowledge.creators": "作成者", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "例:返金ポリシー、配送に関する FAQ、エスカレーション手順 - カスタマー サポートの質問に使用します", "newKnowledge.detailErrorDescription": "このナレッジベースをロードできませんでした。もう一度やり直してください。", "newKnowledge.detailErrorTitle": "何か問題が発生しました", + "newKnowledge.disableSource": "無効にする", "newKnowledge.discardDraftConfirm": "下書きを破棄", "newKnowledge.discardDraftDescription": "このナレッジベースの下書きに加えた変更は失われます。", "newKnowledge.discardDraftTitle": "このナレッジベースの下書きを破棄しますか?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "ソースを接続すると、そのドキュメントは同期され、自動的にインデックス化されてすぐに利用できます。管理する設定はありません。従来のナレッジベースもこれまでどおり動作します。", "newKnowledge.guideTitle": "新しいナレッジベースへようこそ ✨", "newKnowledge.illustrationHeadline": "コンテンツを一度接続すれば、すべてのアプリが最新のナレッジで回答します。", + "newKnowledge.lastSyncColumn": "最終同期", "newKnowledge.learnMore": "詳細を見る", "newKnowledge.leavePartialSetupConfirm": "セットアップを終了", "newKnowledge.leavePartialSetupDescription": "ナレッジベースは作成されましたが、権限を確認できませんでした。終了してもナレッジベースは保持され、アクセス権は後で確認できます。", "newKnowledge.leavePartialSetupTitle": "未完了のセットアップを終了しますか?", "newKnowledge.legacy": "旧バージョン", "newKnowledge.loadMore": "さらに読み込む", + "newKnowledge.moreProviders": "もっと見る", "newKnowledge.name": "ナレッジ名", "newKnowledge.namePlaceholder": "例:カスタマーサポートハンドブック", "newKnowledge.nameRequired": "ナレッジベース名を入力します。", "newKnowledge.new": "新バージョン", "newKnowledge.noDescription": "説明なし", + "newKnowledge.noMatchingSources": "この検索に一致するソースはありません。", "newKnowledge.notFoundDescription": "このナレッジ ベースは削除されているか、アクセスできない可能性があります。", "newKnowledge.notFoundTitle": "ナレッジベースが見つかりません", + "newKnowledge.onlineDocuments": "オンライン文書", + "newKnowledge.onlineDrive": "オンラインドライブ", "newKnowledge.permission": "許可", "newKnowledge.permissionAllMembers": "ワークスペース · すべてのメンバーが表示および編集できます", "newKnowledge.permissionOnlyMe": "私だけ", "newKnowledge.permissionRestricted": "ワークスペースの権限では、この設定を変更することはできません。", "newKnowledge.permissionUpdateFailed": "ナレッジベースは作成されましたが、権限を確認できませんでした。再試行してセットアップを完了してください。", + "newKnowledge.providerConnected": "{{provider}} が接続されました", + "newKnowledge.providerLabel": "プロバイダーを選択する", + "newKnowledge.providerLoadFailed": "プロバイダーを読み込めませんでした", + "newKnowledge.providerNotConfigured": "{{provider}} が構成されていません", + "newKnowledge.providerNotConfiguredDescription": "{{provider}} を使用して Web サイトをクロールするための API キーまたはエンドポイント URL を追加します。", + "newKnowledge.providerUnavailable": "このプロバイダーは利用できません。", "newKnowledge.readOnlyEmpty": "最初のナレッジベースの作成をワークスペース編集者に依頼してください。", + "newKnowledge.refreshConnectionStatus": "ステータスの更新", + "newKnowledge.refreshingConnection": "爽やか…", + "newKnowledge.removeSource": "ソースを削除", + "newKnowledge.retryProviderLoad": "再試行", "newKnowledge.routeUnavailable": "このセクションは、次のセットアップ手順で使用できるようになります。", + "newKnowledge.searchSources": "ソースを検索", + "newKnowledge.sourceActions": "{{name}} のアクション", + "newKnowledge.sourceColumn": "ソース", + "newKnowledge.sourceFilterLabel": "ソースをステータスでフィルタリングする", + "newKnowledge.sourceStatus.active": "アクティブ", + "newKnowledge.sourceStatus.disabled": "無効", + "newKnowledge.sourceStatus.error": "エラー", + "newKnowledge.sourceStatus.syncing": "同期中", + "newKnowledge.sourceSyncFailed": "失敗", + "newKnowledge.sourceType.connector": "接続済みアプリ", + "newKnowledge.sourceType.object-storage": "オンラインドライブ", + "newKnowledge.sourceType.upload": "アップロード", + "newKnowledge.sourceType.web": "ウェブサイトのクロール", + "newKnowledge.sourceTypeLabel": "ソースタイプ", "newKnowledge.sources": "情報源", + "newKnowledge.sourcesDescription": "知識がどこから来たのか、その新鮮さはどれくらいか、最後の同期が成功したかどうか。", + "newKnowledge.sourcesEmptyDescription": "Web サイト、ワークスペース、ドライブを接続すると、Dify が同期して最新の状態に保つため、検索が中断されることはありません。", + "newKnowledge.sourcesEmptyTitle": "ソースがまだ接続されていません", + "newKnowledge.sourcesErrorDescription": "ソースをロードできませんでした。もう一度やり直してください。", + "newKnowledge.sourcesErrorTitle": "ソースをロードできませんでした", "newKnowledge.startEmpty": "空から始める", "newKnowledge.startEmptyDescription": "今すぐ作成し、コンテンツは後から追加できます。", "newKnowledge.startWith": "から始める", "newKnowledge.startWithHelp": "いつでもソースやドキュメントを追加できます。", + "newKnowledge.statusColumn": "ステータス", + "newKnowledge.syncNow": "今すぐ同期", + "newKnowledge.syncPolicyColumn": "同期ポリシー", "newKnowledge.tags": "タグ", "newKnowledge.unavailableDescription": "このワークスペースでは現在 KnowledgeFS を利用できません。", "newKnowledge.unavailableTitle": "新しいナレッジは利用できません", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "ファイルをアップロード", "newKnowledge.uploadFilesDescription": "コンピューターからファイルを追加すると、作成時にすぐインデックス化されます。", "newKnowledge.viewLabel": "ナレッジ表示", + "newKnowledge.websiteCrawl": "ウェブサイトのクロール", "noExternalKnowledge": "外部ナレッジベース連携 API がありません。ここをクリックして作成してください", "parentMode.fullDoc": "全体", "parentMode.paragraph": "段落", diff --git a/web/i18n/ko-KR/dataset.json b/web/i18n/ko-KR/dataset.json index 846ad252aa6..b900b8833b3 100644 --- a/web/i18n/ko-KR/dataset.json +++ b/web/i18n/ko-KR/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "고품질과 경제적 지식 베이스의 혼합을 위해서는 재순위 모델이 필요합니다.", "mixtureInternalAndExternalTip": "리랭크 모델은 내부 및 외부 지식의 혼합에 필요합니다.", "multimodal": "멀티모달", + "newKnowledge.actionsColumn": "작업", + "newKnowledge.addSource": "소스 추가", + "newKnowledge.addSourceDescription": "이 지식 베이스에 소스를 연결하세요. 자동으로 동기화되고 최신 상태로 유지됩니다.", + "newKnowledge.allSources": "모든 소스", "newKnowledge.appsUnavailable": "앱 —개", + "newKnowledge.authKind.api-key": "API 키", + "newKnowledge.authKind.endpoint": "종점", + "newKnowledge.authenticationMethod": "인증 방법", "newKnowledge.backToList": "지식 베이스로 돌아가기", + "newKnowledge.booleanFalse": "아니요", + "newKnowledge.booleanTrue": "예", + "newKnowledge.cancelAddSource": "취소", "newKnowledge.cardType": "지식 공간", + "newKnowledge.configureProvider": "{{provider}} 구성", + "newKnowledge.connectProvider": "{{provider}} 연결", "newKnowledge.connectSource": "소스 연결", "newKnowledge.connectSourceDescription": "콘텐츠가 Notion, 웹사이트 및 기타 서비스와 계속 동기화됩니다.", + "newKnowledge.connectingProvider": "연결 중…", + "newKnowledge.connectionFailed": "{{provider}}을 연결할 수 없습니다. 자격 증명을 다시 입력하고 다시 시도하세요.", + "newKnowledge.connectionNeedsAttention": "{{provider}} 연결에 주의가 필요합니다.", + "newKnowledge.connectionNeedsAttentionDescription": "웹사이트 소스를 추가하기 전에 연결을 새로 고치세요.", + "newKnowledge.connectionProvisioning": "{{provider}}이 연결 중입니다.", + "newKnowledge.connectionRefreshFailed": "이 연결을 새로 고칠 수 없습니다. 다시 시도해 보세요.", + "newKnowledge.crawlSetupUnavailableDescription": "크롤링 워크플로를 사용할 수 있을 때까지 웹사이트 크롤링 구성이 비활성화됩니다.", "newKnowledge.createFailed": "이 기술 자료를 만들 수 없습니다. 액세스 권한을 확인하고 다시 시도하세요.", "newKnowledge.createTitle": "지식 창조", "newKnowledge.creators": "생성자", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "예를 들어 환불 정책, 배송 FAQ, 에스컬레이션 단계 - 고객 지원 질문에 사용", "newKnowledge.detailErrorDescription": "이 기술 자료를 로드할 수 없습니다. 다시 시도해 보세요.", "newKnowledge.detailErrorTitle": "문제가 발생했습니다.", + "newKnowledge.disableSource": "비활성화", "newKnowledge.discardDraftConfirm": "초안 삭제", "newKnowledge.discardDraftDescription": "이 지식 베이스 초안의 변경 사항이 삭제됩니다.", "newKnowledge.discardDraftTitle": "이 지식 베이스 초안을 삭제할까요?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "소스를 연결하면 문서가 계속 동기화되고 자동으로 인덱싱되어 바로 사용할 수 있습니다. 관리할 설정은 없습니다. 기존 지식 베이스도 그대로 작동합니다.", "newKnowledge.guideTitle": "새로운 지식 베이스를 만나보세요 ✨", "newKnowledge.illustrationHeadline": "콘텐츠를 한 번 연결하면 모든 앱이 최신 지식으로 답변합니다.", + "newKnowledge.lastSyncColumn": "마지막 동기화", "newKnowledge.learnMore": "자세히 알아보기", "newKnowledge.leavePartialSetupConfirm": "설정 나가기", "newKnowledge.leavePartialSetupDescription": "지식 베이스가 생성되었지만 권한을 확인하지 못했습니다. 나가도 지식 베이스는 유지되며 나중에 액세스 권한을 검토할 수 있습니다.", "newKnowledge.leavePartialSetupTitle": "완료되지 않은 설정을 나갈까요?", "newKnowledge.legacy": "레거시", "newKnowledge.loadMore": "더 보기", + "newKnowledge.moreProviders": "더보기", "newKnowledge.name": "지식 이름", "newKnowledge.namePlaceholder": "예를 들어 고객 지원 핸드북", "newKnowledge.nameRequired": "기술 자료 이름을 입력하세요.", "newKnowledge.new": "신규", "newKnowledge.noDescription": "설명 없음", + "newKnowledge.noMatchingSources": "이 검색과 일치하는 소스가 없습니다.", "newKnowledge.notFoundDescription": "이 기술 자료가 삭제되었거나 액세스 권한이 없을 수 있습니다.", "newKnowledge.notFoundTitle": "기술 자료를 찾을 수 없습니다.", + "newKnowledge.onlineDocuments": "온라인 문서", + "newKnowledge.onlineDrive": "온라인 드라이브", "newKnowledge.permission": "허가", "newKnowledge.permissionAllMembers": "작업공간 · 모든 구성원이 보고 편집할 수 있습니다.", "newKnowledge.permissionOnlyMe": "나만", "newKnowledge.permissionRestricted": "작업공간 권한으로 인해 이 설정을 변경할 수 없습니다.", "newKnowledge.permissionUpdateFailed": "지식 베이스가 생성되었지만 권한을 확인하지 못했습니다. 다시 시도하여 설정을 완료하세요.", + "newKnowledge.providerConnected": "{{provider}} 연결됨", + "newKnowledge.providerLabel": "제공자 선택", + "newKnowledge.providerLoadFailed": "제공자를 로드할 수 없습니다.", + "newKnowledge.providerNotConfigured": "{{provider}}이 구성되지 않았습니다.", + "newKnowledge.providerNotConfiguredDescription": "{{provider}}을(를) 사용하여 웹사이트를 크롤링하려면 API 키 또는 엔드포인트 URL을 추가하세요.", + "newKnowledge.providerUnavailable": "이 제공자를 사용할 수 없습니다.", "newKnowledge.readOnlyEmpty": "워크스페이스 편집자에게 첫 번째 지식 베이스 생성을 요청하세요.", + "newKnowledge.refreshConnectionStatus": "새로 고침 상태", + "newKnowledge.refreshingConnection": "상쾌하다…", + "newKnowledge.removeSource": "소스 제거", + "newKnowledge.retryProviderLoad": "재시도", "newKnowledge.routeUnavailable": "이 섹션은 다음 설정 단계에서 사용할 수 있습니다.", + "newKnowledge.searchSources": "소스 검색", + "newKnowledge.sourceActions": "{{name}}에 대한 작업", + "newKnowledge.sourceColumn": "출처", + "newKnowledge.sourceFilterLabel": "상태별로 소스 필터링", + "newKnowledge.sourceStatus.active": "활성", + "newKnowledge.sourceStatus.disabled": "비활성화됨", + "newKnowledge.sourceStatus.error": "오류", + "newKnowledge.sourceStatus.syncing": "동기화 중", + "newKnowledge.sourceSyncFailed": "실패", + "newKnowledge.sourceType.connector": "연결된 앱", + "newKnowledge.sourceType.object-storage": "온라인 드라이브", + "newKnowledge.sourceType.upload": "업로드", + "newKnowledge.sourceType.web": "웹사이트 크롤링", + "newKnowledge.sourceTypeLabel": "소스 유형", "newKnowledge.sources": "출처", + "newKnowledge.sourcesDescription": "지식의 출처, 정보의 최신성, 마지막 동기화 성공 여부.", + "newKnowledge.sourcesEmptyDescription": "웹사이트, 워크스페이스 또는 드라이브를 연결하면 Dify가 동기화하고 최신 상태로 유지하여 검색이 중단되지 않도록 합니다.", + "newKnowledge.sourcesEmptyTitle": "아직 연결된 소스가 없습니다.", + "newKnowledge.sourcesErrorDescription": "소스를 로드할 수 없습니다. 다시 시도해 보세요.", + "newKnowledge.sourcesErrorTitle": "소스를 로드할 수 없습니다.", "newKnowledge.startEmpty": "빈 상태로 시작", "newKnowledge.startEmptyDescription": "지금 만들고 콘텐츠는 나중에 추가하세요.", "newKnowledge.startWith": "다음으로 시작", "newKnowledge.startWithHelp": "언제든지 더 많은 소스나 문서를 추가할 수 있습니다.", + "newKnowledge.statusColumn": "상태", + "newKnowledge.syncNow": "지금 동기화", + "newKnowledge.syncPolicyColumn": "동기화 정책", "newKnowledge.tags": "태그", "newKnowledge.unavailableDescription": "현재 이 워크스페이스에서 KnowledgeFS를 사용할 수 없습니다.", "newKnowledge.unavailableTitle": "새 지식을 사용할 수 없음", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "파일 업로드", "newKnowledge.uploadFilesDescription": "컴퓨터에서 파일을 추가하면 생성 즉시 인덱싱됩니다.", "newKnowledge.viewLabel": "지식 보기", + "newKnowledge.websiteCrawl": "웹사이트 크롤링", "noExternalKnowledge": "아직 외부 지식 API 가 없으므로 여기를 클릭하여 생성하십시오.", "parentMode.fullDoc": "전체 문서", "parentMode.paragraph": "단락", diff --git a/web/i18n/nl-NL/dataset.json b/web/i18n/nl-NL/dataset.json index 167c5741423..28bbe9e1501 100644 --- a/web/i18n/nl-NL/dataset.json +++ b/web/i18n/nl-NL/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "The Rerank model is required for mixture of high quality and economical knowledge bases.", "mixtureInternalAndExternalTip": "The Rerank model is required for mixture of internal and external knowledge.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Acties", + "newKnowledge.addSource": "Bron toevoegen", + "newKnowledge.addSourceDescription": "Verbind een bron met deze kennisbank: deze synchroniseert automatisch en blijft actueel.", + "newKnowledge.allSources": "Alle bronnen", "newKnowledge.appsUnavailable": "— apps", + "newKnowledge.authKind.api-key": "API-sleutel", + "newKnowledge.authKind.endpoint": "Eindpunt", + "newKnowledge.authenticationMethod": "Authenticatiemethode", "newKnowledge.backToList": "Terug naar kennisbanken", + "newKnowledge.booleanFalse": "Nee", + "newKnowledge.booleanTrue": "Ja", + "newKnowledge.cancelAddSource": "Annuleren", "newKnowledge.cardType": "Kennisruimte", + "newKnowledge.configureProvider": "{{provider}} configureren", + "newKnowledge.connectProvider": "{{provider}} verbinden", "newKnowledge.connectSource": "Bron verbinden", "newKnowledge.connectSourceDescription": "Inhoud blijft gesynchroniseerd met Notion, websites en andere diensten.", + "newKnowledge.connectingProvider": "Verbinden…", + "newKnowledge.connectionFailed": "We konden {{provider}} niet verbinden. Voer de inloggegevens opnieuw in en probeer het opnieuw.", + "newKnowledge.connectionNeedsAttention": "{{provider}}-verbinding heeft aandacht nodig", + "newKnowledge.connectionNeedsAttentionDescription": "Vernieuw de verbinding voordat u een websitebron toevoegt.", + "newKnowledge.connectionProvisioning": "{{provider}} maakt verbinding", + "newKnowledge.connectionRefreshFailed": "We konden deze verbinding niet vernieuwen. Probeer het opnieuw.", + "newKnowledge.crawlSetupUnavailableDescription": "De configuratie van de websitecrawl is uitgeschakeld totdat de crawlworkflow beschikbaar is.", "newKnowledge.createFailed": "We konden deze kennisbank niet creëren. Controleer uw toegang en probeer het opnieuw.", "newKnowledge.createTitle": "Creëer kennis", "newKnowledge.creators": "Makers", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "bijv. Terugbetalingsbeleid, veelgestelde vragen over verzending en escalatiestappen - gebruik deze voor vragen over klantenondersteuning", "newKnowledge.detailErrorDescription": "We kunnen deze kennisbank niet laden. Probeer het opnieuw.", "newKnowledge.detailErrorTitle": "Er is iets misgegaan", + "newKnowledge.disableSource": "Uitschakelen", "newKnowledge.discardDraftConfirm": "Concept verwijderen", "newKnowledge.discardDraftDescription": "Uw wijzigingen aan dit kennisbankconcept gaan verloren.", "newKnowledge.discardDraftTitle": "Dit kennisbankconcept verwijderen?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Verbind een bron en de documenten blijven gesynchroniseerd, automatisch geïndexeerd en direct klaar voor gebruik, zonder beheer. Je bestaande kennisbanken blijven ongewijzigd werken.", "newKnowledge.guideTitle": "Maak kennis met de nieuwe Kennisbank ✨", "newKnowledge.illustrationHeadline": "Koppel je content één keer — elke app antwoordt met de meest actuele kennis.", + "newKnowledge.lastSyncColumn": "Laatste synchronisatie", "newKnowledge.learnMore": "Meer informatie", "newKnowledge.leavePartialSetupConfirm": "Configuratie verlaten", "newKnowledge.leavePartialSetupDescription": "De kennisbank is gemaakt, maar de machtiging kon niet worden bevestigd. Als u vertrekt, blijft de kennisbank behouden; u kunt de toegang later controleren.", "newKnowledge.leavePartialSetupTitle": "Onvoltooide configuratie verlaten?", "newKnowledge.legacy": "Oud", "newKnowledge.loadMore": "Meer laden", + "newKnowledge.moreProviders": "View more", "newKnowledge.name": "Kennis naam", "newKnowledge.namePlaceholder": "bijv. Handboek voor klantenondersteuning", "newKnowledge.nameRequired": "Voer een kennisbanknaam in.", "newKnowledge.new": "Nieuw", "newKnowledge.noDescription": "Geen beschrijving", + "newKnowledge.noMatchingSources": "Er zijn geen bronnen die overeenkomen met deze zoekopdracht.", "newKnowledge.notFoundDescription": "Deze kennisbank is mogelijk verwijderd of u heeft mogelijk geen toegang.", "newKnowledge.notFoundTitle": "Kennisbank niet gevonden", + "newKnowledge.onlineDocuments": "Onlinedocumenten", + "newKnowledge.onlineDrive": "Online rijden", "newKnowledge.permission": "Toestemming", "newKnowledge.permissionAllMembers": "Werkruimte · alle leden kunnen bekijken en bewerken", "newKnowledge.permissionOnlyMe": "Alleen ik", "newKnowledge.permissionRestricted": "Uw werkruimtemachtigingen staan het wijzigen van deze instelling niet toe.", "newKnowledge.permissionUpdateFailed": "De kennisbank is gemaakt, maar de machtiging kon niet worden bevestigd. Probeer opnieuw om de configuratie te voltooien.", + "newKnowledge.providerConnected": "{{provider}} aangesloten", + "newKnowledge.providerLabel": "Select a provider", + "newKnowledge.providerLoadFailed": "Providers konden niet laden", + "newKnowledge.providerNotConfigured": "{{provider}} is niet geconfigureerd", + "newKnowledge.providerNotConfiguredDescription": "Voeg een API-sleutel of eindpunt-URL toe om websites te crawlen met {{provider}}.", + "newKnowledge.providerUnavailable": "Deze aanbieder is niet beschikbaar.", "newKnowledge.readOnlyEmpty": "Vraag een werkruimte-editor om de eerste kennisbank te maken.", + "newKnowledge.refreshConnectionStatus": "Vernieuwingsstatus", + "newKnowledge.refreshingConnection": "Verfrissen…", + "newKnowledge.removeSource": "Bron verwijderen", + "newKnowledge.retryProviderLoad": "Probeer het opnieuw", "newKnowledge.routeUnavailable": "Deze sectie komt beschikbaar in de volgende installatiestap.", + "newKnowledge.searchSources": "Zoek bronnen", + "newKnowledge.sourceActions": "Acties voor {{name}}", + "newKnowledge.sourceColumn": "Bron", + "newKnowledge.sourceFilterLabel": "Filter bronnen op status", + "newKnowledge.sourceStatus.active": "Actief", + "newKnowledge.sourceStatus.disabled": "Uitgeschakeld", + "newKnowledge.sourceStatus.error": "Fout", + "newKnowledge.sourceStatus.syncing": "Synchroniseren", + "newKnowledge.sourceSyncFailed": "Mislukt", + "newKnowledge.sourceType.connector": "Verbonden app", + "newKnowledge.sourceType.object-storage": "Online rijden", + "newKnowledge.sourceType.upload": "Uploaden", + "newKnowledge.sourceType.web": "Websitecrawl", + "newKnowledge.sourceTypeLabel": "Brontype", "newKnowledge.sources": "Bronnen", + "newKnowledge.sourcesDescription": "Waar kennis vandaan komt, hoe vers deze is en of de laatste synchronisatie is gelukt.", + "newKnowledge.sourcesEmptyDescription": "Koppel een website, werkruimte of schijf — Dify houdt deze gesynchroniseerd en actueel, zodat het ophalen nooit wordt onderbroken.", + "newKnowledge.sourcesEmptyTitle": "Nog geen bronnen aangesloten", + "newKnowledge.sourcesErrorDescription": "We konden de bronnen niet laden. Probeer het opnieuw.", + "newKnowledge.sourcesErrorTitle": "Bronnen konden niet laden", "newKnowledge.startEmpty": "Leeg beginnen", "newKnowledge.startEmptyDescription": "Maak de kennisbank nu en voeg later inhoud toe.", "newKnowledge.startWith": "Begin met", "newKnowledge.startWithHelp": "U kunt op elk gewenst moment meer bronnen of documenten toevoegen.", + "newKnowledge.statusColumn": "Status", + "newKnowledge.syncNow": "Synchroniseer nu", + "newKnowledge.syncPolicyColumn": "Synchronisatiebeleid", "newKnowledge.tags": "Tags", "newKnowledge.unavailableDescription": "KnowledgeFS is momenteel niet beschikbaar voor deze werkruimte.", "newKnowledge.unavailableTitle": "Nieuwe kennis is niet beschikbaar", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Bestanden uploaden", "newKnowledge.uploadFilesDescription": "Voeg bestanden van je computer toe; ze worden geïndexeerd zodra je ze aanmaakt.", "newKnowledge.viewLabel": "Kennisweergave", + "newKnowledge.websiteCrawl": "Websitecrawl", "noExternalKnowledge": "There is no External Knowledge API yet, click here to create", "parentMode.fullDoc": "Full-doc", "parentMode.paragraph": "Paragraph", diff --git a/web/i18n/pl-PL/dataset.json b/web/i18n/pl-PL/dataset.json index 813fae6842e..4e5f52b731b 100644 --- a/web/i18n/pl-PL/dataset.json +++ b/web/i18n/pl-PL/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Model ponownego rankingu jest wymagany dla mieszanki wysokiej jakości i ekonomicznych baz wiedzy.", "mixtureInternalAndExternalTip": "Model Rerank jest wymagany do połączenia wiedzy wewnętrznej i zewnętrznej.", "multimodal": "Multimodalny", + "newKnowledge.actionsColumn": "Działania", + "newKnowledge.addSource": "Dodaj źródło", + "newKnowledge.addSourceDescription": "Podłącz źródło do tej bazy wiedzy — synchronizuje się ona automatycznie i pozostaje aktualna.", + "newKnowledge.allSources": "Wszystkie źródła", "newKnowledge.appsUnavailable": "— aplikacji", + "newKnowledge.authKind.api-key": "Klucz API", + "newKnowledge.authKind.endpoint": "Punkt końcowy", + "newKnowledge.authenticationMethod": "Metoda uwierzytelniania", "newKnowledge.backToList": "Powrót do baz wiedzy", + "newKnowledge.booleanFalse": "Nie", + "newKnowledge.booleanTrue": "Tak", + "newKnowledge.cancelAddSource": "Anuluj", "newKnowledge.cardType": "Przestrzeń wiedzy", + "newKnowledge.configureProvider": "Skonfiguruj {{provider}}", + "newKnowledge.connectProvider": "Połącz {{provider}}", "newKnowledge.connectSource": "Połącz źródło", "newKnowledge.connectSourceDescription": "Treści pozostają zsynchronizowane z Notion, witrynami internetowymi i innymi usługami.", + "newKnowledge.connectingProvider": "Łączenie…", + "newKnowledge.connectionFailed": "Nie mogliśmy połączyć {{provider}}. Wprowadź ponownie dane uwierzytelniające i spróbuj jeszcze raz.", + "newKnowledge.connectionNeedsAttention": "Połączenie {{provider}} wymaga uwagi", + "newKnowledge.connectionNeedsAttentionDescription": "Odśwież połączenie przed dodaniem źródła strony internetowej.", + "newKnowledge.connectionProvisioning": "{{provider}} łączy się", + "newKnowledge.connectionRefreshFailed": "Nie mogliśmy odświeżyć tego połączenia. Spróbuj ponownie.", + "newKnowledge.crawlSetupUnavailableDescription": "Konfiguracja indeksowania witryny jest wyłączona do czasu udostępnienia przepływu pracy indeksowania.", "newKnowledge.createFailed": "Nie mogliśmy utworzyć tej bazy wiedzy. Sprawdź swój dostęp i spróbuj ponownie.", "newKnowledge.createTitle": "Twórz wiedzę", "newKnowledge.creators": "Twórcy", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "np. Polityka zwrotów, często zadawane pytania dotyczące wysyłki i etapy eskalacji — używaj w przypadku pytań do obsługi klienta", "newKnowledge.detailErrorDescription": "Nie mogliśmy załadować tej bazy wiedzy. Spróbuj ponownie.", "newKnowledge.detailErrorTitle": "Coś poszło nie tak", + "newKnowledge.disableSource": "Wyłącz", "newKnowledge.discardDraftConfirm": "Odrzuć wersję roboczą", "newKnowledge.discardDraftDescription": "Zmiany w tej wersji roboczej bazy wiedzy zostaną utracone.", "newKnowledge.discardDraftTitle": "Odrzucić tę wersję roboczą bazy wiedzy?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Połącz źródło, a jego dokumenty pozostaną zsynchronizowane, automatycznie zindeksowane i gotowe do użycia, bez konieczności zarządzania konfiguracją. Dotychczasowe bazy wiedzy będą nadal działać bez zmian.", "newKnowledge.guideTitle": "Poznaj nową bazę wiedzy ✨", "newKnowledge.illustrationHeadline": "Połącz treści raz — każda aplikacja odpowie, korzystając z najnowszej wiedzy.", + "newKnowledge.lastSyncColumn": "Ostatnia synchronizacja", "newKnowledge.learnMore": "Dowiedz się więcej", "newKnowledge.leavePartialSetupConfirm": "Opuść konfigurację", "newKnowledge.leavePartialSetupDescription": "Baza wiedzy została utworzona, ale nie udało się potwierdzić jej uprawnień. Po opuszczeniu baza wiedzy zostanie zachowana; dostęp można sprawdzić później.", "newKnowledge.leavePartialSetupTitle": "Opuścić nieukończoną konfigurację?", "newKnowledge.legacy": "Starsza wersja", "newKnowledge.loadMore": "Załaduj więcej", + "newKnowledge.moreProviders": "Zobacz więcej", "newKnowledge.name": "Nazwa wiedzy", "newKnowledge.namePlaceholder": "np. Podręcznik obsługi klienta", "newKnowledge.nameRequired": "Wprowadź nazwę bazy wiedzy.", "newKnowledge.new": "Nowa wersja", "newKnowledge.noDescription": "Brak opisu", + "newKnowledge.noMatchingSources": "Żadne źródła nie pasują do tego wyszukiwania.", "newKnowledge.notFoundDescription": "Ta baza wiedzy mogła zostać usunięta lub możesz nie mieć do niej dostępu.", "newKnowledge.notFoundTitle": "Nie znaleziono bazy wiedzy", + "newKnowledge.onlineDocuments": "Dokumenty online", + "newKnowledge.onlineDrive": "Dysk online", "newKnowledge.permission": "Pozwolenie", "newKnowledge.permissionAllMembers": "Obszar roboczy · wszyscy członkowie mogą przeglądać i edytować", "newKnowledge.permissionOnlyMe": "Tylko ja", "newKnowledge.permissionRestricted": "Uprawnienia Twojego obszaru roboczego nie pozwalają na zmianę tego ustawienia.", "newKnowledge.permissionUpdateFailed": "Baza wiedzy została utworzona, ale nie udało się potwierdzić jej uprawnień. Spróbuj ponownie, aby ukończyć konfigurację.", + "newKnowledge.providerConnected": "{{provider}} podłączony", + "newKnowledge.providerLabel": "Wybierz dostawcę", + "newKnowledge.providerLoadFailed": "Dostawcy nie mogli załadować", + "newKnowledge.providerNotConfigured": "{{provider}} nie jest skonfigurowany", + "newKnowledge.providerNotConfiguredDescription": "Dodaj klucz API lub adres URL punktu końcowego, aby indeksować strony internetowe za pomocą {{provider}}.", + "newKnowledge.providerUnavailable": "Ten dostawca jest niedostępny.", "newKnowledge.readOnlyEmpty": "Poproś edytora obszaru roboczego o utworzenie pierwszej bazy wiedzy.", + "newKnowledge.refreshConnectionStatus": "Odśwież status", + "newKnowledge.refreshingConnection": "Odświeżanie…", + "newKnowledge.removeSource": "Usuń źródło", + "newKnowledge.retryProviderLoad": "Spróbuj ponownie", "newKnowledge.routeUnavailable": "Ta sekcja będzie dostępna w następnym kroku konfiguracji.", + "newKnowledge.searchSources": "Wyszukaj źródła", + "newKnowledge.sourceActions": "Działania dla {{name}}", + "newKnowledge.sourceColumn": "Źródło", + "newKnowledge.sourceFilterLabel": "Filtruj źródła według stanu", + "newKnowledge.sourceStatus.active": "Aktywny", + "newKnowledge.sourceStatus.disabled": "Wyłączone", + "newKnowledge.sourceStatus.error": "Błąd", + "newKnowledge.sourceStatus.syncing": "Synchronizacja", + "newKnowledge.sourceSyncFailed": "Niepowodzenie", + "newKnowledge.sourceType.connector": "Połączona aplikacja", + "newKnowledge.sourceType.object-storage": "Dysk online", + "newKnowledge.sourceType.upload": "Prześlij", + "newKnowledge.sourceType.web": "Indeksowanie witryny", + "newKnowledge.sourceTypeLabel": "Typ źródła", "newKnowledge.sources": "Źródła", + "newKnowledge.sourcesDescription": "Skąd pochodzi wiedza, jak bardzo jest świeża i czy ostatnia synchronizacja się powiodła.", + "newKnowledge.sourcesEmptyDescription": "Połącz witrynę, obszar roboczy lub dysk — Dify zadba o synchronizację i aktualność, dzięki czemu wyszukiwanie nigdy nie zostanie przerwane.", + "newKnowledge.sourcesEmptyTitle": "Żadne źródła nie są jeszcze podłączone", + "newKnowledge.sourcesErrorDescription": "Nie mogliśmy załadować źródeł. Spróbuj ponownie.", + "newKnowledge.sourcesErrorTitle": "Nie udało się załadować źródeł", "newKnowledge.startEmpty": "Zacznij od pustej", "newKnowledge.startEmptyDescription": "Utwórz ją teraz, a zawartość dodaj później.", "newKnowledge.startWith": "Zacznij od", "newKnowledge.startWithHelp": "W dowolnym momencie możesz dodać więcej źródeł lub dokumentów.", + "newKnowledge.statusColumn": "Stan", + "newKnowledge.syncNow": "Synchronizuj teraz", + "newKnowledge.syncPolicyColumn": "Polityka synchronizacji", "newKnowledge.tags": "Tagi", "newKnowledge.unavailableDescription": "KnowledgeFS nie jest obecnie dostępny dla tego obszaru roboczego.", "newKnowledge.unavailableTitle": "Nowa wiedza jest niedostępna", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Prześlij pliki", "newKnowledge.uploadFilesDescription": "Dodaj pliki z komputera — zostaną zindeksowane od razu po utworzeniu.", "newKnowledge.viewLabel": "Widok wiedzy", + "newKnowledge.websiteCrawl": "Indeksowanie witryny", "noExternalKnowledge": "Nie ma jeszcze interfejsu API wiedzy zewnętrznej, kliknij tutaj, aby utworzyć", "parentMode.fullDoc": "Pełna wersja dokumentu", "parentMode.paragraph": "Akapit", diff --git a/web/i18n/pt-BR/dataset.json b/web/i18n/pt-BR/dataset.json index 10897d32ee1..5466dbc9dfe 100644 --- a/web/i18n/pt-BR/dataset.json +++ b/web/i18n/pt-BR/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "O modelo de reclassificação é necessário para a mistura de bases de conhecimento de alta qualidade e econômicas.", "mixtureInternalAndExternalTip": "O modelo de Reclassificação é necessário para a mistura de conhecimento interno e externo.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Ações", + "newKnowledge.addSource": "Adicionar fonte", + "newKnowledge.addSourceDescription": "Conecte uma fonte a esta base de conhecimento — ela sincroniza automaticamente e permanece atualizada.", + "newKnowledge.allSources": "Todas as fontes", "newKnowledge.appsUnavailable": "— apps", + "newKnowledge.authKind.api-key": "Chave de API", + "newKnowledge.authKind.endpoint": "Ponto final", + "newKnowledge.authenticationMethod": "Método de autenticação", "newKnowledge.backToList": "Voltar às bases de conhecimento", + "newKnowledge.booleanFalse": "Não", + "newKnowledge.booleanTrue": "Sim", + "newKnowledge.cancelAddSource": "Cancelar", "newKnowledge.cardType": "Espaço de conhecimento", + "newKnowledge.configureProvider": "Configurar {{provider}}", + "newKnowledge.connectProvider": "Conectar {{provider}}", "newKnowledge.connectSource": "Conectar uma fonte", "newKnowledge.connectSourceDescription": "O conteúdo permanece sincronizado com Notion, sites e outros serviços.", + "newKnowledge.connectingProvider": "Conectando…", + "newKnowledge.connectionFailed": "Não foi possível conectar o {{provider}}. Insira novamente a credencial e tente novamente.", + "newKnowledge.connectionNeedsAttention": "Conexão {{provider}} precisa de atenção", + "newKnowledge.connectionNeedsAttentionDescription": "Atualize a conexão antes de adicionar uma fonte de site.", + "newKnowledge.connectionProvisioning": "{{provider}} está se conectando", + "newKnowledge.connectionRefreshFailed": "Não foi possível atualizar esta conexão. Tente novamente.", + "newKnowledge.crawlSetupUnavailableDescription": "A configuração de rastreamento de sites será desativada até que o fluxo de trabalho de rastreamento esteja disponível.", "newKnowledge.createFailed": "Não foi possível criar esta base de conhecimento. Verifique seu acesso e tente novamente.", "newKnowledge.createTitle": "Crie Conhecimento", "newKnowledge.creators": "Criadores", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "por exemplo Política de reembolso, perguntas frequentes sobre envio e etapas de escalonamento — use para perguntas de suporte ao cliente", "newKnowledge.detailErrorDescription": "Não foi possível carregar esta base de conhecimento. Tente novamente.", "newKnowledge.detailErrorTitle": "Algo deu errado", + "newKnowledge.disableSource": "Desativar", "newKnowledge.discardDraftConfirm": "Descartar rascunho", "newKnowledge.discardDraftDescription": "Suas alterações neste rascunho da base de conhecimento serão perdidas.", "newKnowledge.discardDraftTitle": "Descartar este rascunho da base de conhecimento?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Conecte uma fonte e os documentos permanecerão sincronizados, indexados automaticamente e prontos para uso, sem nada para gerenciar. Suas bases de conhecimento anteriores continuarão funcionando normalmente.", "newKnowledge.guideTitle": "Conheça a nova Base de Conhecimento ✨", "newKnowledge.illustrationHeadline": "Conecte seu conteúdo uma vez — cada aplicativo responderá com o conhecimento mais recente.", + "newKnowledge.lastSyncColumn": "Última sincronização", "newKnowledge.learnMore": "Saiba mais", "newKnowledge.leavePartialSetupConfirm": "Sair da configuração", "newKnowledge.leavePartialSetupDescription": "A base de conhecimento foi criada, mas não foi possível confirmar sua permissão. Ao sair, a base de conhecimento será mantida; você poderá revisar o acesso depois.", "newKnowledge.leavePartialSetupTitle": "Sair da configuração incompleta?", "newKnowledge.legacy": "Legado", "newKnowledge.loadMore": "Carregar mais", + "newKnowledge.moreProviders": "Ver mais", "newKnowledge.name": "Nome do conhecimento", "newKnowledge.namePlaceholder": "por exemplo Manual de Suporte ao Cliente", "newKnowledge.nameRequired": "Insira um nome para a base de conhecimento.", "newKnowledge.new": "Novo", "newKnowledge.noDescription": "Sem descrição", + "newKnowledge.noMatchingSources": "Nenhuma fonte corresponde a esta pesquisa.", "newKnowledge.notFoundDescription": "Esta base de conhecimento pode ter sido excluída ou você pode não ter acesso.", "newKnowledge.notFoundTitle": "Base de conhecimento não encontrada", + "newKnowledge.onlineDocuments": "Documentos on-line", + "newKnowledge.onlineDrive": "Unidade on-line", "newKnowledge.permission": "Permissão", "newKnowledge.permissionAllMembers": "Espaço de trabalho · todos os membros podem visualizar e editar", "newKnowledge.permissionOnlyMe": "Só eu", "newKnowledge.permissionRestricted": "As permissões do seu espaço de trabalho não permitem alterar essa configuração.", "newKnowledge.permissionUpdateFailed": "A base de conhecimento foi criada, mas não foi possível confirmar sua permissão. Tente novamente para concluir a configuração.", + "newKnowledge.providerConnected": "{{provider}} conectado", + "newKnowledge.providerLabel": "Selecione um provedor", + "newKnowledge.providerLoadFailed": "Os provedores não conseguiram carregar", + "newKnowledge.providerNotConfigured": "{{provider}} não está configurado", + "newKnowledge.providerNotConfiguredDescription": "Adicione uma chave de API ou URL de endpoint para rastrear sites com {{provider}}.", + "newKnowledge.providerUnavailable": "Este provedor não está disponível.", "newKnowledge.readOnlyEmpty": "Peça a um editor do espaço de trabalho para criar a primeira base de conhecimento.", + "newKnowledge.refreshConnectionStatus": "Atualizar status", + "newKnowledge.refreshingConnection": "Refrescante…", + "newKnowledge.removeSource": "Remover fonte", + "newKnowledge.retryProviderLoad": "Tentar novamente", "newKnowledge.routeUnavailable": "Esta seção estará disponível na próxima etapa de configuração.", + "newKnowledge.searchSources": "Fontes de pesquisa", + "newKnowledge.sourceActions": "Ações para {{name}}", + "newKnowledge.sourceColumn": "Fonte", + "newKnowledge.sourceFilterLabel": "Filtrar fontes por status", + "newKnowledge.sourceStatus.active": "Ativo", + "newKnowledge.sourceStatus.disabled": "Desativado", + "newKnowledge.sourceStatus.error": "Erro", + "newKnowledge.sourceStatus.syncing": "Sincronizando", + "newKnowledge.sourceSyncFailed": "Falhou", + "newKnowledge.sourceType.connector": "Aplicativo conectado", + "newKnowledge.sourceType.object-storage": "Unidade on-line", + "newKnowledge.sourceType.upload": "Carregar", + "newKnowledge.sourceType.web": "Rastreamento de site", + "newKnowledge.sourceTypeLabel": "Tipo de fonte", "newKnowledge.sources": "Fontes", + "newKnowledge.sourcesDescription": "De onde vem o conhecimento, quão recente ele é e se a última sincronização foi bem-sucedida.", + "newKnowledge.sourcesEmptyDescription": "Conecte um site, espaço de trabalho ou drive — o Dify mantém tudo sincronizado e atualizado para que a recuperação nunca seja interrompida.", + "newKnowledge.sourcesEmptyTitle": "Nenhuma fonte conectada ainda", + "newKnowledge.sourcesErrorDescription": "Não foi possível carregar as fontes. Tente novamente.", + "newKnowledge.sourcesErrorTitle": "Não foi possível carregar as fontes", "newKnowledge.startEmpty": "Começar vazia", "newKnowledge.startEmptyDescription": "Crie agora e adicione conteúdo depois.", "newKnowledge.startWith": "Comece com", "newKnowledge.startWithHelp": "Você pode adicionar mais fontes ou documentos a qualquer momento.", + "newKnowledge.statusColumn": "Estado", + "newKnowledge.syncNow": "Sincronize agora", + "newKnowledge.syncPolicyColumn": "Política de sincronização", "newKnowledge.tags": "Tags", "newKnowledge.unavailableDescription": "O KnowledgeFS não está disponível para este espaço de trabalho no momento.", "newKnowledge.unavailableTitle": "O Novo Conhecimento não está disponível", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Enviar arquivos", "newKnowledge.uploadFilesDescription": "Adicione arquivos do seu computador; eles são indexados assim que você os cria.", "newKnowledge.viewLabel": "Visualização de conhecimento", + "newKnowledge.websiteCrawl": "Rastreamento de site", "noExternalKnowledge": "Ainda não existe uma API de conhecimento externo, clique aqui para criar", "parentMode.fullDoc": "Documento completo", "parentMode.paragraph": "Parágrafo", diff --git a/web/i18n/ro-RO/dataset.json b/web/i18n/ro-RO/dataset.json index 58fc6162e18..9fb28ef61c0 100644 --- a/web/i18n/ro-RO/dataset.json +++ b/web/i18n/ro-RO/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Modelul de reclasificare este necesar pentru amestecul de baze de cunoștințe de înaltă calitate și economice.", "mixtureInternalAndExternalTip": "Modelul Rerank este necesar pentru amestecul de cunoștințe interne și externe.", "multimodal": "Multimodal", + "newKnowledge.actionsColumn": "Acțiuni", + "newKnowledge.addSource": "Adăugați sursa", + "newKnowledge.addSourceDescription": "Conectați o sursă la această bază de cunoștințe — se sincronizează automat și rămâne actuală.", + "newKnowledge.allSources": "Toate sursele", "newKnowledge.appsUnavailable": "— aplicații", + "newKnowledge.authKind.api-key": "cheie API", + "newKnowledge.authKind.endpoint": "Punct final", + "newKnowledge.authenticationMethod": "Metoda de autentificare", "newKnowledge.backToList": "Înapoi la bazele de cunoștințe", + "newKnowledge.booleanFalse": "Nu", + "newKnowledge.booleanTrue": "Da", + "newKnowledge.cancelAddSource": "Anula", "newKnowledge.cardType": "Spațiu de cunoștințe", + "newKnowledge.configureProvider": "Configurați {{provider}}", + "newKnowledge.connectProvider": "Conectați {{provider}}", "newKnowledge.connectSource": "Conectează o sursă", "newKnowledge.connectSourceDescription": "Conținutul rămâne sincronizat cu Notion, site-uri web și alte servicii.", + "newKnowledge.connectingProvider": "Se conectează...", + "newKnowledge.connectionFailed": "Nu am putut conecta {{provider}}. Reintroduceți acreditările și încercați din nou.", + "newKnowledge.connectionNeedsAttention": "Conexiunea {{provider}} necesită atenție", + "newKnowledge.connectionNeedsAttentionDescription": "Reîmprospătați conexiunea înainte de a adăuga o sursă de site.", + "newKnowledge.connectionProvisioning": "{{provider}} se conectează", + "newKnowledge.connectionRefreshFailed": "Nu am putut reîmprospăta această conexiune. Încearcă din nou.", + "newKnowledge.crawlSetupUnavailableDescription": "Configurarea accesării cu crawlere a site-ului este dezactivată până când fluxul de lucru cu crawlere este disponibil.", "newKnowledge.createFailed": "Nu am putut crea această bază de cunoștințe. Verificați accesul și încercați din nou.", "newKnowledge.createTitle": "Creați cunoștințe", "newKnowledge.creators": "Creatori", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "de ex. Politica de rambursare, întrebări frecvente despre expediere și pași de escaladare — utilizați pentru întrebările de asistență pentru clienți", "newKnowledge.detailErrorDescription": "Nu am putut încărca această bază de cunoștințe. Încearcă din nou.", "newKnowledge.detailErrorTitle": "Ceva a mers prost", + "newKnowledge.disableSource": "Dezactivați", "newKnowledge.discardDraftConfirm": "Renunță la schiță", "newKnowledge.discardDraftDescription": "Modificările aduse acestei schițe a bazei de cunoștințe se vor pierde.", "newKnowledge.discardDraftTitle": "Renunțați la această schiță a bazei de cunoștințe?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Conectează o sursă, iar documentele ei rămân sincronizate, indexate automat și gata de utilizare, fără nimic de administrat. Bazele de cunoștințe existente continuă să funcționeze ca înainte.", "newKnowledge.guideTitle": "Descoperă noua bază de cunoștințe ✨", "newKnowledge.illustrationHeadline": "Conectează conținutul o singură dată — fiecare aplicație răspunde cu cele mai noi informații.", + "newKnowledge.lastSyncColumn": "Ultima sincronizare", "newKnowledge.learnMore": "Află mai multe", "newKnowledge.leavePartialSetupConfirm": "Ieși din configurare", "newKnowledge.leavePartialSetupDescription": "Baza de cunoștințe a fost creată, dar permisiunea nu a putut fi confirmată. Dacă ieșiți, baza de cunoștințe va fi păstrată; puteți verifica accesul mai târziu.", "newKnowledge.leavePartialSetupTitle": "Ieșiți din configurarea incompletă?", "newKnowledge.legacy": "Versiune veche", "newKnowledge.loadMore": "Încarcă mai multe", + "newKnowledge.moreProviders": "Vezi mai mult", "newKnowledge.name": "Nume de cunoștințe", "newKnowledge.namePlaceholder": "de ex. Manual de asistență pentru clienți", "newKnowledge.nameRequired": "Introduceți un nume de bază de cunoștințe.", "newKnowledge.new": "Versiune nouă", "newKnowledge.noDescription": "Fără descriere", + "newKnowledge.noMatchingSources": "Nicio sursă nu corespunde acestei căutări.", "newKnowledge.notFoundDescription": "Este posibil ca această bază de cunoștințe să fi fost ștearsă sau este posibil să nu aveți acces.", "newKnowledge.notFoundTitle": "Baza de cunoștințe nu a fost găsită", + "newKnowledge.onlineDocuments": "Documente online", + "newKnowledge.onlineDrive": "Conducere online", "newKnowledge.permission": "Permisiune", "newKnowledge.permissionAllMembers": "Spațiu de lucru · toți membrii pot vizualiza și edita", "newKnowledge.permissionOnlyMe": "Doar eu", "newKnowledge.permissionRestricted": "Permisiunile pentru spațiul de lucru nu permit modificarea acestei setări.", "newKnowledge.permissionUpdateFailed": "Baza de cunoștințe a fost creată, dar permisiunea nu a putut fi confirmată. Încercați din nou pentru a finaliza configurarea.", + "newKnowledge.providerConnected": "{{provider}} conectat", + "newKnowledge.providerLabel": "Selectați un furnizor", + "newKnowledge.providerLoadFailed": "Furnizorii nu s-au putut încărca", + "newKnowledge.providerNotConfigured": "{{provider}} nu este configurat", + "newKnowledge.providerNotConfiguredDescription": "Adăugați o cheie API sau o adresă URL a punctului final pentru a accesa cu crawlere site-urile web cu {{provider}}.", + "newKnowledge.providerUnavailable": "Acest furnizor nu este disponibil.", "newKnowledge.readOnlyEmpty": "Cere unui editor al spațiului de lucru să creeze prima bază de cunoștințe.", + "newKnowledge.refreshConnectionStatus": "Starea de reîmprospătare", + "newKnowledge.refreshingConnection": "Înviorare…", + "newKnowledge.removeSource": "Eliminați sursa", + "newKnowledge.retryProviderLoad": "Reîncercați", "newKnowledge.routeUnavailable": "Această secțiune va deveni disponibilă în următorul pas de configurare.", + "newKnowledge.searchSources": "Căutați surse", + "newKnowledge.sourceActions": "Acțiuni pentru {{name}}", + "newKnowledge.sourceColumn": "Sursă", + "newKnowledge.sourceFilterLabel": "Filtrați sursele după stare", + "newKnowledge.sourceStatus.active": "Activ", + "newKnowledge.sourceStatus.disabled": "Dezactivat", + "newKnowledge.sourceStatus.error": "Eroare", + "newKnowledge.sourceStatus.syncing": "Sincronizare", + "newKnowledge.sourceSyncFailed": "Eșuat", + "newKnowledge.sourceType.connector": "Aplicație conectată", + "newKnowledge.sourceType.object-storage": "Conducere online", + "newKnowledge.sourceType.upload": "Încărcați", + "newKnowledge.sourceType.web": "Accesare cu crawlere a site-ului", + "newKnowledge.sourceTypeLabel": "Tip sursă", "newKnowledge.sources": "Surse", + "newKnowledge.sourcesDescription": "De unde provin cunoștințele, cât de proaspete sunt și dacă ultima sincronizare a reușit.", + "newKnowledge.sourcesEmptyDescription": "Conectează un site, un spațiu de lucru sau o unitate — Dify îl menține sincronizat și actualizat, astfel încât regăsirea să nu fie întreruptă niciodată.", + "newKnowledge.sourcesEmptyTitle": "Nicio sursă conectată încă", + "newKnowledge.sourcesErrorDescription": "Nu am putut încărca sursele. Încearcă din nou.", + "newKnowledge.sourcesErrorTitle": "Sursele nu s-au putut încărca", "newKnowledge.startEmpty": "Începe de la zero", "newKnowledge.startEmptyDescription": "Creeaz-o acum și adaugă conținut mai târziu.", "newKnowledge.startWith": "Începe cu", "newKnowledge.startWithHelp": "Puteți adăuga oricând mai multe surse sau documente.", + "newKnowledge.statusColumn": "Stare", + "newKnowledge.syncNow": "Sincronizează acum", + "newKnowledge.syncPolicyColumn": "Politica de sincronizare", "newKnowledge.tags": "Etichete", "newKnowledge.unavailableDescription": "KnowledgeFS nu este disponibil momentan pentru acest spațiu de lucru.", "newKnowledge.unavailableTitle": "Noua bază de cunoștințe nu este disponibilă", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Încarcă fișiere", "newKnowledge.uploadFilesDescription": "Adaugă fișiere de pe computer — sunt indexate imediat ce le creezi.", "newKnowledge.viewLabel": "Vizualizare cunoștințe", + "newKnowledge.websiteCrawl": "Accesare cu crawlere a site-ului", "noExternalKnowledge": "Nu există încă un API de cunoștințe externe, faceți clic aici pentru a crea", "parentMode.fullDoc": "Documentar complet", "parentMode.paragraph": "Paragraf", diff --git a/web/i18n/ru-RU/dataset.json b/web/i18n/ru-RU/dataset.json index 1e34b4644a7..243aef0c313 100644 --- a/web/i18n/ru-RU/dataset.json +++ b/web/i18n/ru-RU/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Для смешивания высококачественных и экономичных баз знаний требуется модель переранжирования.", "mixtureInternalAndExternalTip": "Модель Rerank необходима для смешивания внутренних и внешних знаний.", "multimodal": "Мультимодальный", + "newKnowledge.actionsColumn": "Действия", + "newKnowledge.addSource": "Добавить источник", + "newKnowledge.addSourceDescription": "Подключите источник к этой базе знаний — она синхронизируется автоматически и остается актуальной.", + "newKnowledge.allSources": "Все источники", "newKnowledge.appsUnavailable": "— приложений", + "newKnowledge.authKind.api-key": "API-ключ", + "newKnowledge.authKind.endpoint": "Конечная точка", + "newKnowledge.authenticationMethod": "Метод аутентификации", "newKnowledge.backToList": "Вернуться к базам знаний", + "newKnowledge.booleanFalse": "Нет", + "newKnowledge.booleanTrue": "Да", + "newKnowledge.cancelAddSource": "Отмена", "newKnowledge.cardType": "Пространство знаний", + "newKnowledge.configureProvider": "Настроить {{provider}}", + "newKnowledge.connectProvider": "Подключите {{provider}}", "newKnowledge.connectSource": "Подключить источник", "newKnowledge.connectSourceDescription": "Контент остаётся синхронизированным с Notion, веб-сайтами и другими сервисами.", + "newKnowledge.connectingProvider": "Подключение…", + "newKnowledge.connectionFailed": "Нам не удалось подключить {{provider}}. Повторно введите учетные данные и повторите попытку.", + "newKnowledge.connectionNeedsAttention": "Соединение {{provider}} требует внимания", + "newKnowledge.connectionNeedsAttentionDescription": "Обновите соединение перед добавлением источника веб-сайта.", + "newKnowledge.connectionProvisioning": "{{provider}} подключается", + "newKnowledge.connectionRefreshFailed": "Не удалось обновить это соединение. Попробуйте еще раз.", + "newKnowledge.crawlSetupUnavailableDescription": "Конфигурация сканирования веб-сайта отключена до тех пор, пока не будет доступен рабочий процесс сканирования.", "newKnowledge.createFailed": "Мы не смогли создать эту базу знаний. Проверьте доступ и повторите попытку.", "newKnowledge.createTitle": "Создавайте знания", "newKnowledge.creators": "Создатели", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "например Политика возврата, часто задаваемые вопросы о доставке и шаги эскалации — используйте для вопросов поддержки клиентов.", "newKnowledge.detailErrorDescription": "Нам не удалось загрузить эту базу знаний. Попробуйте еще раз.", "newKnowledge.detailErrorTitle": "Что-то пошло не так", + "newKnowledge.disableSource": "Отключить", "newKnowledge.discardDraftConfirm": "Удалить черновик", "newKnowledge.discardDraftDescription": "Изменения в этом черновике базы знаний будут потеряны.", "newKnowledge.discardDraftTitle": "Удалить этот черновик базы знаний?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Подключите источник, и его документы будут синхронизироваться, автоматически индексироваться и сразу станут готовы к работе — без дополнительной настройки. Ваши прежние базы знаний продолжат работать как раньше.", "newKnowledge.guideTitle": "Познакомьтесь с новой базой знаний ✨", "newKnowledge.illustrationHeadline": "Подключите контент один раз — и каждое приложение будет отвечать на основе самых свежих знаний.", + "newKnowledge.lastSyncColumn": "Последняя синхронизация", "newKnowledge.learnMore": "Подробнее", "newKnowledge.leavePartialSetupConfirm": "Выйти из настройки", "newKnowledge.leavePartialSetupDescription": "База знаний создана, но подтвердить её разрешения не удалось. При выходе база знаний сохранится; доступ можно проверить позже.", "newKnowledge.leavePartialSetupTitle": "Выйти из незавершённой настройки?", "newKnowledge.legacy": "Предыдущая версия", "newKnowledge.loadMore": "Загрузить ещё", + "newKnowledge.moreProviders": "Подробнее", "newKnowledge.name": "Название знания", "newKnowledge.namePlaceholder": "например Руководство по поддержке клиентов", "newKnowledge.nameRequired": "Введите название базы знаний.", "newKnowledge.new": "Новая версия", "newKnowledge.noDescription": "Нет описания", + "newKnowledge.noMatchingSources": "Ни один источник не соответствует этому запросу.", "newKnowledge.notFoundDescription": "Возможно, эта база знаний была удалена, или у вас нет доступа.", "newKnowledge.notFoundTitle": "База знаний не найдена", + "newKnowledge.onlineDocuments": "Онлайн-документы", + "newKnowledge.onlineDrive": "Онлайн-диск", "newKnowledge.permission": "Разрешение", "newKnowledge.permissionAllMembers": "Рабочая область · все участники могут просматривать и редактировать", "newKnowledge.permissionOnlyMe": "Только я", "newKnowledge.permissionRestricted": "Разрешения вашей рабочей области не позволяют изменить этот параметр.", "newKnowledge.permissionUpdateFailed": "База знаний создана, но подтвердить её разрешения не удалось. Повторите попытку, чтобы завершить настройку.", + "newKnowledge.providerConnected": "{{provider}} подключен", + "newKnowledge.providerLabel": "Выберите провайдера", + "newKnowledge.providerLoadFailed": "Поставщикам не удалось загрузить", + "newKnowledge.providerNotConfigured": "{{provider}} не настроено", + "newKnowledge.providerNotConfiguredDescription": "Добавьте ключ API или URL-адрес конечной точки для сканирования веб-сайтов с помощью {{provider}}.", + "newKnowledge.providerUnavailable": "Этот провайдер недоступен.", "newKnowledge.readOnlyEmpty": "Попросите редактора рабочего пространства создать первую базу знаний.", + "newKnowledge.refreshConnectionStatus": "Обновить статус", + "newKnowledge.refreshingConnection": "Обновление…", + "newKnowledge.removeSource": "Удалить источник", + "newKnowledge.retryProviderLoad": "Повторить попытку", "newKnowledge.routeUnavailable": "Этот раздел станет доступен на следующем этапе настройки.", + "newKnowledge.searchSources": "Поиск источников", + "newKnowledge.sourceActions": "Действия для {{name}}", + "newKnowledge.sourceColumn": "Источник", + "newKnowledge.sourceFilterLabel": "Фильтровать источники по статусу", + "newKnowledge.sourceStatus.active": "Активен", + "newKnowledge.sourceStatus.disabled": "Отключено", + "newKnowledge.sourceStatus.error": "Ошибка", + "newKnowledge.sourceStatus.syncing": "Синхронизация", + "newKnowledge.sourceSyncFailed": "Не удалось", + "newKnowledge.sourceType.connector": "Подключенное приложение", + "newKnowledge.sourceType.object-storage": "Онлайн-диск", + "newKnowledge.sourceType.upload": "Загрузить", + "newKnowledge.sourceType.web": "Сканирование веб-сайта", + "newKnowledge.sourceTypeLabel": "Тип источника", "newKnowledge.sources": "Источники", + "newKnowledge.sourcesDescription": "Откуда берутся знания, насколько они свежие и успешна ли последняя синхронизация.", + "newKnowledge.sourcesEmptyDescription": "Подключите сайт, рабочее пространство или диск — Dify будет поддерживать синхронизацию и актуальность, чтобы поиск никогда не прерывался.", + "newKnowledge.sourcesEmptyTitle": "Источники пока не подключены", + "newKnowledge.sourcesErrorDescription": "Не удалось загрузить исходники. Попробуйте еще раз.", + "newKnowledge.sourcesErrorTitle": "Не удалось загрузить исходники.", "newKnowledge.startEmpty": "Начать с пустой", "newKnowledge.startEmptyDescription": "Создайте сейчас, а контент добавьте позже.", "newKnowledge.startWith": "Начните с", "newKnowledge.startWithHelp": "Вы можете добавить больше источников или документов в любое время.", + "newKnowledge.statusColumn": "Статус", + "newKnowledge.syncNow": "Синхронизировать сейчас", + "newKnowledge.syncPolicyColumn": "Политика синхронизации", "newKnowledge.tags": "Теги", "newKnowledge.unavailableDescription": "KnowledgeFS сейчас недоступен для этого рабочего пространства.", "newKnowledge.unavailableTitle": "Новая база знаний недоступна", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Загрузить файлы", "newKnowledge.uploadFilesDescription": "Добавьте файлы с компьютера — они будут проиндексированы сразу после создания.", "newKnowledge.viewLabel": "Вид базы знаний", + "newKnowledge.websiteCrawl": "Сканирование веб-сайта", "noExternalKnowledge": "У нас еще нет External Knowledge API, нажмите здесь, чтобы создать", "parentMode.fullDoc": "Полный документ", "parentMode.paragraph": "Параграф", diff --git a/web/i18n/sl-SI/dataset.json b/web/i18n/sl-SI/dataset.json index 9eaa52fdae8..c18944a43a7 100644 --- a/web/i18n/sl-SI/dataset.json +++ b/web/i18n/sl-SI/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Model za ponovno razvrščanje je potreben za mešanico baz znanja visoke kakovosti in varčnih baz.", "mixtureInternalAndExternalTip": "Model za ponovno razvrščanje je potreben za mešanico notranjega in zunanjega znanja.", "multimodal": "Multimodalen", + "newKnowledge.actionsColumn": "Dejanja", + "newKnowledge.addSource": "Dodaj vir", + "newKnowledge.addSourceDescription": "Povežite vir s to bazo znanja — samodejno se sinhronizira in ostane sveža.", + "newKnowledge.allSources": "Vsi viri", "newKnowledge.appsUnavailable": "— aplikacij", + "newKnowledge.authKind.api-key": "API ključ", + "newKnowledge.authKind.endpoint": "Končna točka", + "newKnowledge.authenticationMethod": "Metoda avtentikacije", "newKnowledge.backToList": "Nazaj k bazam znanja", + "newKnowledge.booleanFalse": "Št", + "newKnowledge.booleanTrue": "Da", + "newKnowledge.cancelAddSource": "Prekliči", "newKnowledge.cardType": "Prostor znanja", + "newKnowledge.configureProvider": "Konfigurirajte {{provider}}", + "newKnowledge.connectProvider": "Povežite {{provider}}", "newKnowledge.connectSource": "Poveži vir", "newKnowledge.connectSourceDescription": "Vsebina ostaja sinhronizirana z Notionom, spletnimi mesti in drugimi storitvami.", + "newKnowledge.connectingProvider": "Povezovanje ...", + "newKnowledge.connectionFailed": "{{provider}} nismo mogli povezati. Znova vnesite poverilnico in poskusite znova.", + "newKnowledge.connectionNeedsAttention": "Povezava {{provider}} zahteva pozornost", + "newKnowledge.connectionNeedsAttentionDescription": "Osvežite povezavo, preden dodate vir spletnega mesta.", + "newKnowledge.connectionProvisioning": "{{provider}} vzpostavlja povezavo", + "newKnowledge.connectionRefreshFailed": "Te povezave nismo mogli osvežiti. Poskusite znova.", + "newKnowledge.crawlSetupUnavailableDescription": "Konfiguracija iskanja po vsebini spletnega mesta je onemogočena, dokler potek dela po vsebini ni na voljo.", "newKnowledge.createFailed": "Te baze znanja nismo mogli ustvariti. Preverite dostop in poskusite znova.", "newKnowledge.createTitle": "Ustvarite znanje", "newKnowledge.creators": "Ustvarjalci", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "npr. Politika vračil, pogosta vprašanja o pošiljanju in koraki za eskalacijo — uporabite za vprašanja podpore strankam", "newKnowledge.detailErrorDescription": "Te baze znanja nismo mogli naložiti. Poskusite znova.", "newKnowledge.detailErrorTitle": "Nekaj je šlo narobe", + "newKnowledge.disableSource": "Onemogoči", "newKnowledge.discardDraftConfirm": "Zavrzi osnutek", "newKnowledge.discardDraftDescription": "Spremembe tega osnutka zbirke znanja bodo izgubljene.", "newKnowledge.discardDraftTitle": "Želite zavreči ta osnutek zbirke znanja?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Povežite vir in njegovi dokumenti bodo ostali sinhronizirani, samodejno indeksirani in pripravljeni za uporabo brez dodatnega upravljanja. Vaše obstoječe baze znanja bodo še naprej delovale kot doslej.", "newKnowledge.guideTitle": "Spoznajte novo bazo znanja ✨", "newKnowledge.illustrationHeadline": "Vsebino povežite enkrat — vsaka aplikacija bo odgovarjala z najnovejšim znanjem.", + "newKnowledge.lastSyncColumn": "Zadnja sinhronizacija", "newKnowledge.learnMore": "Več informacij", "newKnowledge.leavePartialSetupConfirm": "Zapusti nastavitev", "newKnowledge.leavePartialSetupDescription": "Zbirka znanja je bila ustvarjena, vendar njenega dovoljenja ni bilo mogoče potrditi. Če zapustite nastavitev, bo zbirka znanja ohranjena; dostop lahko preverite pozneje.", "newKnowledge.leavePartialSetupTitle": "Želite zapustiti nedokončano nastavitev?", "newKnowledge.legacy": "Staro", "newKnowledge.loadMore": "Naloži več", + "newKnowledge.moreProviders": "Oglejte si več", "newKnowledge.name": "Ime znanja", "newKnowledge.namePlaceholder": "npr. Priročnik za podporo strankam", "newKnowledge.nameRequired": "Vnesite ime baze znanja.", "newKnowledge.new": "Novo", "newKnowledge.noDescription": "Brez opisa", + "newKnowledge.noMatchingSources": "Noben vir ne ustreza temu iskanju.", "newKnowledge.notFoundDescription": "Ta baza znanja je bila morda izbrisana ali pa nimate dostopa.", "newKnowledge.notFoundTitle": "Baza znanja ni bila najdena", + "newKnowledge.onlineDocuments": "Spletni dokumenti", + "newKnowledge.onlineDrive": "Spletna vožnja", "newKnowledge.permission": "Dovoljenje", "newKnowledge.permissionAllMembers": "Delovni prostor · vsi člani si lahko ogledujejo in urejajo", "newKnowledge.permissionOnlyMe": "Samo jaz", "newKnowledge.permissionRestricted": "Vaša dovoljenja za delovni prostor ne dovoljujejo spreminjanja te nastavitve.", "newKnowledge.permissionUpdateFailed": "Zbirka znanja je bila ustvarjena, vendar njenega dovoljenja ni bilo mogoče potrditi. Poskusite znova, da dokončate nastavitev.", + "newKnowledge.providerConnected": "{{provider}} je povezan", + "newKnowledge.providerLabel": "Izberi ponudnika", + "newKnowledge.providerLoadFailed": "Ponudnikov ni bilo mogoče naložiti", + "newKnowledge.providerNotConfigured": "{{provider}} ni konfiguriran", + "newKnowledge.providerNotConfiguredDescription": "Dodajte ključ API ali URL končne točke za iskanje po spletnih mestih z {{provider}}.", + "newKnowledge.providerUnavailable": "Ta ponudnik ni dosegljiv.", "newKnowledge.readOnlyEmpty": "Prosite urednika delovnega prostora, naj ustvari prvo bazo znanja.", + "newKnowledge.refreshConnectionStatus": "Osveži stanje", + "newKnowledge.refreshingConnection": "Osvežitev …", + "newKnowledge.removeSource": "Odstrani vir", + "newKnowledge.retryProviderLoad": "Poskusi znova", "newKnowledge.routeUnavailable": "Ta razdelek bo na voljo v naslednjem koraku nastavitve.", + "newKnowledge.searchSources": "Iskanje virov", + "newKnowledge.sourceActions": "Dejanja za {{name}}", + "newKnowledge.sourceColumn": "Vir", + "newKnowledge.sourceFilterLabel": "Filtrirajte vire po statusu", + "newKnowledge.sourceStatus.active": "Aktivno", + "newKnowledge.sourceStatus.disabled": "Onemogočeno", + "newKnowledge.sourceStatus.error": "Napaka", + "newKnowledge.sourceStatus.syncing": "Sinhronizacija", + "newKnowledge.sourceSyncFailed": "Neuspešno", + "newKnowledge.sourceType.connector": "Povezana aplikacija", + "newKnowledge.sourceType.object-storage": "Spletna vožnja", + "newKnowledge.sourceType.upload": "Naloži", + "newKnowledge.sourceType.web": "Iskanje po vsebini spletne strani", + "newKnowledge.sourceTypeLabel": "Vrsta vira", "newKnowledge.sources": "Viri", + "newKnowledge.sourcesDescription": "Od kod prihaja znanje, kako sveže je in ali je zadnja sinhronizacija uspela.", + "newKnowledge.sourcesEmptyDescription": "Povežite spletno mesto, delovni prostor ali pogon — Dify ga ohranja sinhroniziranega in posodobljenega, da pridobivanje podatkov nikoli ni prekinjeno.", + "newKnowledge.sourcesEmptyTitle": "Ni še povezanih virov", + "newKnowledge.sourcesErrorDescription": "Virov ni bilo mogoče naložiti. Poskusite znova.", + "newKnowledge.sourcesErrorTitle": "Virov ni bilo mogoče naložiti", "newKnowledge.startEmpty": "Začni prazno", "newKnowledge.startEmptyDescription": "Ustvarite jo zdaj in vsebino dodajte pozneje.", "newKnowledge.startWith": "Začni z", "newKnowledge.startWithHelp": "Kadar koli lahko dodate več virov ali dokumentov.", + "newKnowledge.statusColumn": "Stanje", + "newKnowledge.syncNow": "Sinhroniziraj zdaj", + "newKnowledge.syncPolicyColumn": "Pravilnik o sinhronizaciji", "newKnowledge.tags": "Oznake", "newKnowledge.unavailableDescription": "KnowledgeFS trenutno ni na voljo za ta delovni prostor.", "newKnowledge.unavailableTitle": "Novo znanje ni na voljo", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Naloži datoteke", "newKnowledge.uploadFilesDescription": "Dodajte datoteke iz računalnika — indeksirajo se takoj ob ustvarjanju.", "newKnowledge.viewLabel": "Prikaz znanja", + "newKnowledge.websiteCrawl": "Iskanje po vsebini spletne strani", "noExternalKnowledge": "Zunanjega API-ja za znanje še ni, kliknite tukaj za ustvarjanje", "parentMode.fullDoc": "Celoten dokument", "parentMode.paragraph": "Odstavek", diff --git a/web/i18n/th-TH/dataset.json b/web/i18n/th-TH/dataset.json index 08d4aff7443..21c48405fc1 100644 --- a/web/i18n/th-TH/dataset.json +++ b/web/i18n/th-TH/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "โมเดล Rerank จําเป็นสําหรับการผสมผสานระหว่างฐานความรู้คุณภาพสูงและประหยัด", "mixtureInternalAndExternalTip": "โมเดล Rerank จําเป็นสําหรับการผสมผสานระหว่างความรู้ภายในและภายนอก", "multimodal": "หลายรูปแบบ", + "newKnowledge.actionsColumn": "การดำเนินการ", + "newKnowledge.addSource": "เพิ่มแหล่งที่มา", + "newKnowledge.addSourceDescription": "เชื่อมต่อแหล่งข้อมูลกับฐานความรู้นี้ โดยจะซิงค์โดยอัตโนมัติและมีความสดใหม่อยู่เสมอ", + "newKnowledge.allSources": "แหล่งที่มาทั้งหมด", "newKnowledge.appsUnavailable": "— แอป", + "newKnowledge.authKind.api-key": "คีย์ API", + "newKnowledge.authKind.endpoint": "จุดสิ้นสุด", + "newKnowledge.authenticationMethod": "วิธีการตรวจสอบความถูกต้อง", "newKnowledge.backToList": "กลับสู่ฐานความรู้", + "newKnowledge.booleanFalse": "ไม่", + "newKnowledge.booleanTrue": "ใช่", + "newKnowledge.cancelAddSource": "ยกเลิก", "newKnowledge.cardType": "พื้นที่ความรู้", + "newKnowledge.configureProvider": "กำหนดค่า {{provider}}", + "newKnowledge.connectProvider": "เชื่อมต่อ {{provider}}", "newKnowledge.connectSource": "เชื่อมต่อแหล่งข้อมูล", "newKnowledge.connectSourceDescription": "เนื้อหาจะซิงค์กับ Notion เว็บไซต์ และบริการอื่น ๆ อยู่เสมอ", + "newKnowledge.connectingProvider": "กำลังเชื่อมต่อ...", + "newKnowledge.connectionFailed": "เราไม่สามารถเชื่อมต่อ {{provider}} ได้ ป้อนข้อมูลรับรองอีกครั้งแล้วลองอีกครั้ง", + "newKnowledge.connectionNeedsAttention": "การเชื่อมต่อ {{provider}} ต้องการความสนใจ", + "newKnowledge.connectionNeedsAttentionDescription": "รีเฟรชการเชื่อมต่อก่อนที่จะเพิ่มแหล่งที่มาของเว็บไซต์", + "newKnowledge.connectionProvisioning": "กำลังเชื่อมต่อ {{provider}}", + "newKnowledge.connectionRefreshFailed": "เราไม่สามารถรีเฟรชการเชื่อมต่อนี้ได้ ลองอีกครั้ง", + "newKnowledge.crawlSetupUnavailableDescription": "การกำหนดค่าการรวบรวมข้อมูลเว็บไซต์ถูกปิดใช้งานจนกว่าเวิร์กโฟลว์การรวบรวมข้อมูลจะพร้อมใช้งาน", "newKnowledge.createFailed": "เราไม่สามารถสร้างฐานความรู้นี้ได้ ตรวจสอบการเข้าถึงของคุณแล้วลองอีกครั้ง", "newKnowledge.createTitle": "สร้างองค์ความรู้", "newKnowledge.creators": "ผู้สร้าง", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "เช่น นโยบายการคืนเงิน คำถามที่พบบ่อยเกี่ยวกับการจัดส่ง และขั้นตอนการยกระดับ — ใช้สำหรับคำถามด้านการสนับสนุนลูกค้า", "newKnowledge.detailErrorDescription": "เราไม่สามารถโหลดฐานความรู้นี้ได้ ลองอีกครั้ง", "newKnowledge.detailErrorTitle": "มีบางอย่างผิดพลาด", + "newKnowledge.disableSource": "ปิดการใช้งาน", "newKnowledge.discardDraftConfirm": "ละทิ้งฉบับร่าง", "newKnowledge.discardDraftDescription": "การเปลี่ยนแปลงในฉบับร่างฐานความรู้นี้จะสูญหาย", "newKnowledge.discardDraftTitle": "ละทิ้งฉบับร่างฐานความรู้นี้หรือไม่?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "เชื่อมต่อแหล่งข้อมูล แล้วเอกสารจะซิงค์ ทำดัชนีอัตโนมัติ และพร้อมใช้งานโดยไม่ต้องจัดการการตั้งค่า ฐานความรู้เดิมของคุณยังคงทำงานได้ตามปกติ", "newKnowledge.guideTitle": "พบกับฐานความรู้แบบใหม่ ✨", "newKnowledge.illustrationHeadline": "เชื่อมต่อเนื้อหาครั้งเดียว ทุกแอปจะตอบด้วยความรู้ล่าสุด", + "newKnowledge.lastSyncColumn": "ซิงค์ครั้งล่าสุด", "newKnowledge.learnMore": "เรียนรู้เพิ่มเติม", "newKnowledge.leavePartialSetupConfirm": "ออกจากการตั้งค่า", "newKnowledge.leavePartialSetupDescription": "สร้างฐานความรู้แล้ว แต่ไม่สามารถยืนยันสิทธิ์ได้ หากออก ฐานความรู้จะยังคงอยู่ และคุณสามารถตรวจสอบการเข้าถึงภายหลังได้", "newKnowledge.leavePartialSetupTitle": "ออกจากการตั้งค่าที่ยังไม่เสร็จหรือไม่?", "newKnowledge.legacy": "แบบเดิม", "newKnowledge.loadMore": "โหลดเพิ่มเติม", + "newKnowledge.moreProviders": "ดูเพิ่มเติม", "newKnowledge.name": "ชื่อความรู้", "newKnowledge.namePlaceholder": "เช่น คู่มือการสนับสนุนลูกค้า", "newKnowledge.nameRequired": "ป้อนชื่อฐานความรู้", "newKnowledge.new": "แบบใหม่", "newKnowledge.noDescription": "ไม่มีคำอธิบาย", + "newKnowledge.noMatchingSources": "ไม่มีแหล่งที่มาที่ตรงกับการค้นหานี้", "newKnowledge.notFoundDescription": "ฐานความรู้นี้อาจถูกลบไปแล้วหรือคุณอาจไม่สามารถเข้าถึงได้", "newKnowledge.notFoundTitle": "ไม่พบฐานความรู้", + "newKnowledge.onlineDocuments": "เอกสารออนไลน์", + "newKnowledge.onlineDrive": "ไดรฟ์ออนไลน์", "newKnowledge.permission": "การอนุญาต", "newKnowledge.permissionAllMembers": "พื้นที่ทำงาน · สมาชิกทุกคนสามารถดูและแก้ไขได้", "newKnowledge.permissionOnlyMe": "มีเพียงฉันเท่านั้น", "newKnowledge.permissionRestricted": "สิทธิ์พื้นที่ทำงานของคุณไม่อนุญาตให้เปลี่ยนการตั้งค่านี้", "newKnowledge.permissionUpdateFailed": "สร้างฐานความรู้แล้ว แต่ไม่สามารถยืนยันสิทธิ์ได้ โปรดลองอีกครั้งเพื่อดำเนินการตั้งค่าให้เสร็จ", + "newKnowledge.providerConnected": "เชื่อมต่อ {{provider}} แล้ว", + "newKnowledge.providerLabel": "เลือกผู้ให้บริการ", + "newKnowledge.providerLoadFailed": "ผู้ให้บริการไม่สามารถโหลดได้", + "newKnowledge.providerNotConfigured": "{{provider}} ไม่ได้กำหนดค่า", + "newKnowledge.providerNotConfiguredDescription": "เพิ่มคีย์ API หรือ URL ปลายทางเพื่อรวบรวมข้อมูลเว็บไซต์ด้วย {{provider}}", + "newKnowledge.providerUnavailable": "ผู้ให้บริการนี้ไม่พร้อมใช้งาน", "newKnowledge.readOnlyEmpty": "ขอให้ผู้แก้ไขพื้นที่ทำงานสร้างฐานความรู้แรก", + "newKnowledge.refreshConnectionStatus": "รีเฟรชสถานะ", + "newKnowledge.refreshingConnection": "สดชื่น...", + "newKnowledge.removeSource": "ลบแหล่งสัญญาณ", + "newKnowledge.retryProviderLoad": "ลองอีกครั้ง", "newKnowledge.routeUnavailable": "ส่วนนี้จะพร้อมใช้งานในขั้นตอนการตั้งค่าถัดไป", + "newKnowledge.searchSources": "แหล่งค้นหา", + "newKnowledge.sourceActions": "การดำเนินการสำหรับ {{name}}", + "newKnowledge.sourceColumn": "ที่มา", + "newKnowledge.sourceFilterLabel": "กรองแหล่งที่มาตามสถานะ", + "newKnowledge.sourceStatus.active": "แอคทีฟ", + "newKnowledge.sourceStatus.disabled": "ปิดใช้งาน", + "newKnowledge.sourceStatus.error": "เกิดข้อผิดพลาด", + "newKnowledge.sourceStatus.syncing": "กำลังซิงค์", + "newKnowledge.sourceSyncFailed": "ล้มเหลว", + "newKnowledge.sourceType.connector": "แอปที่เชื่อมต่อ", + "newKnowledge.sourceType.object-storage": "ไดรฟ์ออนไลน์", + "newKnowledge.sourceType.upload": "อัปโหลด", + "newKnowledge.sourceType.web": "การรวบรวมข้อมูลเว็บไซต์", + "newKnowledge.sourceTypeLabel": "ประเภทแหล่งสัญญาณ", "newKnowledge.sources": "แหล่งที่มา", + "newKnowledge.sourcesDescription": "ความรู้มาจากไหน ความสดใหม่ และการซิงค์ครั้งล่าสุดสำเร็จหรือไม่", + "newKnowledge.sourcesEmptyDescription": "เชื่อมต่อเว็บไซต์ เวิร์กสเปซ หรือไดรฟ์ — Dify จะซิงค์และอัปเดตข้อมูลให้เสมอ เพื่อให้การเรียกคืนข้อมูลไม่สะดุด", + "newKnowledge.sourcesEmptyTitle": "ยังไม่มีการเชื่อมต่อแหล่งที่มา", + "newKnowledge.sourcesErrorDescription": "เราไม่สามารถโหลดแหล่งที่มาได้ ลองอีกครั้ง", + "newKnowledge.sourcesErrorTitle": "ไม่สามารถโหลดแหล่งที่มาได้", "newKnowledge.startEmpty": "เริ่มจากว่างเปล่า", "newKnowledge.startEmptyDescription": "สร้างตอนนี้แล้วเพิ่มเนื้อหาภายหลัง", "newKnowledge.startWith": "เริ่มต้นด้วย", "newKnowledge.startWithHelp": "คุณสามารถเพิ่มแหล่งที่มาหรือเอกสารเพิ่มเติมได้ตลอดเวลา", + "newKnowledge.statusColumn": "สถานะ", + "newKnowledge.syncNow": "ซิงค์เลย", + "newKnowledge.syncPolicyColumn": "นโยบายการซิงค์", "newKnowledge.tags": "แท็ก", "newKnowledge.unavailableDescription": "ขณะนี้ KnowledgeFS ไม่พร้อมใช้งานสำหรับพื้นที่ทำงานนี้", "newKnowledge.unavailableTitle": "ความรู้แบบใหม่ไม่พร้อมใช้งาน", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "อัปโหลดไฟล์", "newKnowledge.uploadFilesDescription": "เพิ่มไฟล์จากคอมพิวเตอร์ ไฟล์จะถูกทำดัชนีทันทีที่สร้าง", "newKnowledge.viewLabel": "มุมมองความรู้", + "newKnowledge.websiteCrawl": "การรวบรวมข้อมูลเว็บไซต์", "noExternalKnowledge": "ยังไม่มี External Knowledge API คลิกที่นี่เพื่อสร้าง", "parentMode.fullDoc": "เอกสารฉบับเต็ม", "parentMode.paragraph": "วรรค", diff --git a/web/i18n/tr-TR/dataset.json b/web/i18n/tr-TR/dataset.json index efcbc25a1ef..7573d84ea84 100644 --- a/web/i18n/tr-TR/dataset.json +++ b/web/i18n/tr-TR/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Yüksek kaliteli ve ekonomik bilgi tabanlarının karışımı için Yeniden Sıralama modeli gereklidir.", "mixtureInternalAndExternalTip": "Yeniden Sıralama modeli, iç ve dış bilgilerin karışımı için gereklidir.", "multimodal": "Çok Modlu", + "newKnowledge.actionsColumn": "Eylemler", + "newKnowledge.addSource": "Kaynak ekle", + "newKnowledge.addSourceDescription": "Bir kaynağı bu bilgi tabanına bağlayın; otomatik olarak senkronize edilir ve güncel kalır.", + "newKnowledge.allSources": "Tüm kaynaklar", "newKnowledge.appsUnavailable": "— uygulama", + "newKnowledge.authKind.api-key": "API anahtarı", + "newKnowledge.authKind.endpoint": "Uç nokta", + "newKnowledge.authenticationMethod": "Kimlik doğrulama yöntemi", "newKnowledge.backToList": "Bilgi tabanlarına geri dön", + "newKnowledge.booleanFalse": "Hayır", + "newKnowledge.booleanTrue": "Evet", + "newKnowledge.cancelAddSource": "İptal et", "newKnowledge.cardType": "Bilgi alanı", + "newKnowledge.configureProvider": "{{provider}}'ı Yapılandır", + "newKnowledge.connectProvider": "{{provider}}'a bağlanın", "newKnowledge.connectSource": "Kaynak bağla", "newKnowledge.connectSourceDescription": "İçerik Notion, web siteleri ve diğer hizmetlerle senkronize kalır.", + "newKnowledge.connectingProvider": "Bağlanıyor…", + "newKnowledge.connectionFailed": "{{provider}}'a bağlanamadık. Kimlik bilgilerini tekrar girin ve tekrar deneyin.", + "newKnowledge.connectionNeedsAttention": "{{provider}} bağlantısına dikkat edilmesi gerekiyor", + "newKnowledge.connectionNeedsAttentionDescription": "Bir web sitesi kaynağı eklemeden önce bağlantıyı yenileyin.", + "newKnowledge.connectionProvisioning": "{{provider}} bağlanıyor", + "newKnowledge.connectionRefreshFailed": "Bu bağlantıyı yenileyemedik. Tekrar deneyin.", + "newKnowledge.crawlSetupUnavailableDescription": "Web sitesi tarama yapılandırması, tarama iş akışı kullanılabilir olana kadar devre dışı bırakılır.", "newKnowledge.createFailed": "Bu bilgi tabanını oluşturamadık. Erişiminizi kontrol edip tekrar deneyin.", "newKnowledge.createTitle": "Bilgi Yaratın", "newKnowledge.creators": "Oluşturanlar", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "örneğin Geri ödeme politikası, gönderimle ilgili SSS'ler ve üst kademeye yükseltme adımları — müşteri desteği soruları için kullanın", "newKnowledge.detailErrorDescription": "Bu bilgi tabanını yükleyemedik. Tekrar deneyin.", "newKnowledge.detailErrorTitle": "Bir şeyler ters gitti", + "newKnowledge.disableSource": "Devre Dışı Bırak", "newKnowledge.discardDraftConfirm": "Taslağı sil", "newKnowledge.discardDraftDescription": "Bu bilgi tabanı taslağındaki değişiklikleriniz kaybolacak.", "newKnowledge.discardDraftTitle": "Bu bilgi tabanı taslağı silinsin mi?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Bir kaynak bağladığınızda belgeleri senkronize kalır, otomatik olarak indekslenir ve yönetilecek bir kurulum olmadan kullanıma hazır olur. Mevcut bilgi tabanlarınız olduğu gibi çalışmaya devam eder.", "newKnowledge.guideTitle": "Yeni Bilgi Tabanı ile tanışın ✨", "newKnowledge.illustrationHeadline": "İçeriğinizi bir kez bağlayın — her uygulama en güncel bilgilerle yanıt versin.", + "newKnowledge.lastSyncColumn": "Son senkronizasyon", "newKnowledge.learnMore": "Daha fazla bilgi", "newKnowledge.leavePartialSetupConfirm": "Kurulumdan çık", "newKnowledge.leavePartialSetupDescription": "Bilgi tabanı oluşturuldu ancak izni doğrulanamadı. Çıkarsanız bilgi tabanı korunur; erişimi daha sonra gözden geçirebilirsiniz.", "newKnowledge.leavePartialSetupTitle": "Tamamlanmamış kurulumdan çıkılsın mı?", "newKnowledge.legacy": "Eski", "newKnowledge.loadMore": "Daha fazla yükle", + "newKnowledge.moreProviders": "Daha fazla göster", "newKnowledge.name": "Bilgi adı", "newKnowledge.namePlaceholder": "örneğin Müşteri Desteği El Kitabı", "newKnowledge.nameRequired": "Bir bilgi tabanı adı girin.", "newKnowledge.new": "Yeni", "newKnowledge.noDescription": "Açıklama yok", + "newKnowledge.noMatchingSources": "Bu aramayla eşleşen kaynak yok.", "newKnowledge.notFoundDescription": "Bu bilgi tabanı silinmiş olabilir veya erişiminiz olmayabilir.", "newKnowledge.notFoundTitle": "Bilgi tabanı bulunamadı", + "newKnowledge.onlineDocuments": "Çevrimiçi belgeler", + "newKnowledge.onlineDrive": "Çevrimiçi sürücü", "newKnowledge.permission": "İzin", "newKnowledge.permissionAllMembers": "Çalışma alanı · tüm üyeler görüntüleyebilir ve düzenleyebilir", "newKnowledge.permissionOnlyMe": "Sadece ben", "newKnowledge.permissionRestricted": "Çalışma alanı izinleriniz bu ayarın değiştirilmesine izin vermiyor.", "newKnowledge.permissionUpdateFailed": "Bilgi tabanı oluşturuldu ancak izni doğrulanamadı. Kurulumu tamamlamak için yeniden deneyin.", + "newKnowledge.providerConnected": "{{provider}} bağlandı", + "newKnowledge.providerLabel": "Bir sağlayıcı seçin", + "newKnowledge.providerLoadFailed": "Sağlayıcılar yüklenemedi", + "newKnowledge.providerNotConfigured": "{{provider}} yapılandırılmadı", + "newKnowledge.providerNotConfiguredDescription": "{{provider}} ile web sitelerini taramak için bir API anahtarı veya uç nokta URL'si ekleyin.", + "newKnowledge.providerUnavailable": "Bu sağlayıcı kullanılamıyor.", "newKnowledge.readOnlyEmpty": "İlk bilgi tabanını oluşturması için bir çalışma alanı editörüne başvurun.", + "newKnowledge.refreshConnectionStatus": "Durumu yenile", + "newKnowledge.refreshingConnection": "Yenileniyor…", + "newKnowledge.removeSource": "Kaynağı kaldır", + "newKnowledge.retryProviderLoad": "Tekrar dene", "newKnowledge.routeUnavailable": "Bu bölüm bir sonraki kurulum adımında kullanılabilir hale gelecektir.", + "newKnowledge.searchSources": "Kaynakları ara", + "newKnowledge.sourceActions": "{{name}} için eylemler", + "newKnowledge.sourceColumn": "Kaynak", + "newKnowledge.sourceFilterLabel": "Kaynakları duruma göre filtrele", + "newKnowledge.sourceStatus.active": "Aktif", + "newKnowledge.sourceStatus.disabled": "Devre Dışı", + "newKnowledge.sourceStatus.error": "Hata", + "newKnowledge.sourceStatus.syncing": "Senkronizasyon", + "newKnowledge.sourceSyncFailed": "Başarısız", + "newKnowledge.sourceType.connector": "Bağlı uygulama", + "newKnowledge.sourceType.object-storage": "Çevrimiçi sürücü", + "newKnowledge.sourceType.upload": "Yükle", + "newKnowledge.sourceType.web": "Web sitesi taraması", + "newKnowledge.sourceTypeLabel": "Kaynak türü", "newKnowledge.sources": "Kaynaklar", + "newKnowledge.sourcesDescription": "Bilginin nereden geldiği, ne kadar yeni olduğu ve son senkronizasyonun başarılı olup olmadığı.", + "newKnowledge.sourcesEmptyDescription": "Bir web sitesi, çalışma alanı veya sürücü bağlayın — Dify içeriği eşitlenmiş ve güncel tutar, böylece getirme işlemi hiçbir zaman kesintiye uğramaz.", + "newKnowledge.sourcesEmptyTitle": "Henüz bağlı kaynak yok", + "newKnowledge.sourcesErrorDescription": "Kaynakları yükleyemedik. Tekrar deneyin.", + "newKnowledge.sourcesErrorTitle": "Kaynaklar yüklenemedi", "newKnowledge.startEmpty": "Boş başla", "newKnowledge.startEmptyDescription": "Şimdi oluşturun, içeriği daha sonra ekleyin.", "newKnowledge.startWith": "Şununla başla:", "newKnowledge.startWithHelp": "İstediğiniz zaman daha fazla Kaynak veya Belge ekleyebilirsiniz.", + "newKnowledge.statusColumn": "Durum", + "newKnowledge.syncNow": "Şimdi senkronize et", + "newKnowledge.syncPolicyColumn": "Senkronizasyon politikası", "newKnowledge.tags": "Etiketler", "newKnowledge.unavailableDescription": "KnowledgeFS şu anda bu çalışma alanında kullanılamıyor.", "newKnowledge.unavailableTitle": "Yeni Bilgi kullanılamıyor", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Dosya yükle", "newKnowledge.uploadFilesDescription": "Bilgisayarınızdan dosya ekleyin; oluşturduğunuz anda indekslenirler.", "newKnowledge.viewLabel": "Bilgi görünümü", + "newKnowledge.websiteCrawl": "Web sitesi taraması", "noExternalKnowledge": "Henüz Harici Bilgi API'si yok, oluşturmak için buraya tıklayın", "parentMode.fullDoc": "Tam doküman", "parentMode.paragraph": "Paragraf", diff --git a/web/i18n/uk-UA/dataset.json b/web/i18n/uk-UA/dataset.json index bc530231357..a471467b283 100644 --- a/web/i18n/uk-UA/dataset.json +++ b/web/i18n/uk-UA/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Модель перерангування потрібна для суміші високоякісних та економічних баз знань.", "mixtureInternalAndExternalTip": "Модель Rerank необхідна для поєднання внутрішніх і зовнішніх знань.", "multimodal": "Мультимодальний", + "newKnowledge.actionsColumn": "Дії", + "newKnowledge.addSource": "Додати джерело", + "newKnowledge.addSourceDescription": "Підключіть джерело до цієї бази знань — вона автоматично синхронізується та залишається актуальною.", + "newKnowledge.allSources": "Усі джерела", "newKnowledge.appsUnavailable": "— застосунків", + "newKnowledge.authKind.api-key": "API ключ", + "newKnowledge.authKind.endpoint": "Кінцева точка", + "newKnowledge.authenticationMethod": "Метод автентифікації", "newKnowledge.backToList": "Назад до баз знань", + "newKnowledge.booleanFalse": "Ні", + "newKnowledge.booleanTrue": "Так", + "newKnowledge.cancelAddSource": "Скасувати", "newKnowledge.cardType": "Простір знань", + "newKnowledge.configureProvider": "Налаштувати {{provider}}", + "newKnowledge.connectProvider": "Підключіть {{provider}}", "newKnowledge.connectSource": "Підключити джерело", "newKnowledge.connectSourceDescription": "Вміст залишається синхронізованим із Notion, вебсайтами та іншими сервісами.", + "newKnowledge.connectingProvider": "Підключення…", + "newKnowledge.connectionFailed": "Не вдалося підключити {{provider}}. Повторно введіть облікові дані та повторіть спробу.", + "newKnowledge.connectionNeedsAttention": "Підключення {{provider}} потребує уваги", + "newKnowledge.connectionNeedsAttentionDescription": "Оновіть з’єднання, перш ніж додавати джерело веб-сайту.", + "newKnowledge.connectionProvisioning": "{{provider}} підключається", + "newKnowledge.connectionRefreshFailed": "Нам не вдалося оновити це з’єднання. Спробуйте знову.", + "newKnowledge.crawlSetupUnavailableDescription": "Конфігурацію сканування веб-сайту вимкнено, доки робочий процес сканування не стане доступним.", "newKnowledge.createFailed": "Ми не змогли створити цю базу знань. Перевірте свій доступ і повторіть спробу.", "newKnowledge.createTitle": "Створюйте знання", "newKnowledge.creators": "Автори", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "напр. Політика відшкодування, поширені запитання щодо доставки та етапи ескалації — використовуйте для запитань служби підтримки клієнтів", "newKnowledge.detailErrorDescription": "Нам не вдалося завантажити цю базу знань. Спробуйте знову.", "newKnowledge.detailErrorTitle": "Щось пішло не так", + "newKnowledge.disableSource": "Вимкнути", "newKnowledge.discardDraftConfirm": "Відхилити чернетку", "newKnowledge.discardDraftDescription": "Зміни в цій чернетці бази знань буде втрачено.", "newKnowledge.discardDraftTitle": "Відхилити цю чернетку бази знань?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Підключіть джерело, і його документи залишатимуться синхронізованими, автоматично індексуватимуться та будуть готові до використання без додаткового налаштування. Ваші попередні бази знань працюватимуть як і раніше.", "newKnowledge.guideTitle": "Познайомтеся з новою базою знань ✨", "newKnowledge.illustrationHeadline": "Підключіть вміст один раз — і кожна програма відповідатиме на основі найсвіжіших знань.", + "newKnowledge.lastSyncColumn": "Остання синхронізація", "newKnowledge.learnMore": "Докладніше", "newKnowledge.leavePartialSetupConfirm": "Вийти з налаштування", "newKnowledge.leavePartialSetupDescription": "Базу знань створено, але не вдалося підтвердити її дозвіл. Якщо вийти, базу знань буде збережено; доступ можна перевірити пізніше.", "newKnowledge.leavePartialSetupTitle": "Вийти з незавершеного налаштування?", "newKnowledge.legacy": "Попередня версія", "newKnowledge.loadMore": "Завантажити ще", + "newKnowledge.moreProviders": "Дивитись більше", "newKnowledge.name": "Назва знання", "newKnowledge.namePlaceholder": "напр. Посібник із підтримки клієнтів", "newKnowledge.nameRequired": "Введіть назву бази знань.", "newKnowledge.new": "Нова версія", "newKnowledge.noDescription": "Немає опису", + "newKnowledge.noMatchingSources": "Жодне джерело не відповідає цьому запиту.", "newKnowledge.notFoundDescription": "Можливо, цю базу знань було видалено або ви не маєте доступу.", "newKnowledge.notFoundTitle": "База знань не знайдена", + "newKnowledge.onlineDocuments": "Документи онлайн", + "newKnowledge.onlineDrive": "Онлайн драйв", "newKnowledge.permission": "Дозвіл", "newKnowledge.permissionAllMembers": "Робоча область · усі учасники можуть переглядати та редагувати", "newKnowledge.permissionOnlyMe": "Тільки я", "newKnowledge.permissionRestricted": "Дозволи вашої робочої області не дозволяють змінити це налаштування.", "newKnowledge.permissionUpdateFailed": "Базу знань створено, але не вдалося підтвердити її дозвіл. Повторіть спробу, щоб завершити налаштування.", + "newKnowledge.providerConnected": "{{provider}} підключено", + "newKnowledge.providerLabel": "Оберіть провайдера", + "newKnowledge.providerLoadFailed": "Не вдалося завантажити постачальників", + "newKnowledge.providerNotConfigured": "{{provider}} не налаштовано", + "newKnowledge.providerNotConfiguredDescription": "Додайте ключ API або URL-адресу кінцевої точки, щоб сканувати веб-сайти за допомогою {{provider}}.", + "newKnowledge.providerUnavailable": "Цей провайдер недоступний.", "newKnowledge.readOnlyEmpty": "Попросіть редактора робочого простору створити першу базу знань.", + "newKnowledge.refreshConnectionStatus": "Оновити статус", + "newKnowledge.refreshingConnection": "Оновлення…", + "newKnowledge.removeSource": "Видалити джерело", + "newKnowledge.retryProviderLoad": "Спробуйте ще раз", "newKnowledge.routeUnavailable": "Цей розділ стане доступним на наступному кроці налаштування.", + "newKnowledge.searchSources": "Пошук джерел", + "newKnowledge.sourceActions": "Дії для {{name}}", + "newKnowledge.sourceColumn": "Джерело", + "newKnowledge.sourceFilterLabel": "Фільтрувати джерела за статусом", + "newKnowledge.sourceStatus.active": "Активний", + "newKnowledge.sourceStatus.disabled": "Вимкнено", + "newKnowledge.sourceStatus.error": "Помилка", + "newKnowledge.sourceStatus.syncing": "Синхронізація", + "newKnowledge.sourceSyncFailed": "Не вдалося", + "newKnowledge.sourceType.connector": "Підключена програма", + "newKnowledge.sourceType.object-storage": "Онлайн-драйв", + "newKnowledge.sourceType.upload": "Завантажити", + "newKnowledge.sourceType.web": "Сканування веб-сайту", + "newKnowledge.sourceTypeLabel": "Тип джерела", "newKnowledge.sources": "Джерела", + "newKnowledge.sourcesDescription": "Звідки надходять знання, наскільки вони свіжі та чи вдалася остання синхронізація.", + "newKnowledge.sourcesEmptyDescription": "Підключіть сайт, робочий простір або диск — Dify підтримуватиме синхронізацію й актуальність, щоб пошук ніколи не переривався.", + "newKnowledge.sourcesEmptyTitle": "Ще немає підключених джерел", + "newKnowledge.sourcesErrorDescription": "Не вдалося завантажити джерела. Спробуйте знову.", + "newKnowledge.sourcesErrorTitle": "Не вдалося завантажити джерела", "newKnowledge.startEmpty": "Почати з порожньої", "newKnowledge.startEmptyDescription": "Створіть зараз, а вміст додайте пізніше.", "newKnowledge.startWith": "Почніть з", "newKnowledge.startWithHelp": "Ви можете будь-коли додати більше джерел або документів.", + "newKnowledge.statusColumn": "Статус", + "newKnowledge.syncNow": "Синхронізувати зараз", + "newKnowledge.syncPolicyColumn": "Політика синхронізації", "newKnowledge.tags": "Теги", "newKnowledge.unavailableDescription": "KnowledgeFS зараз недоступний для цього робочого простору.", "newKnowledge.unavailableTitle": "Нова база знань недоступна", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Завантажити файли", "newKnowledge.uploadFilesDescription": "Додайте файли з комп’ютера — вони індексуються одразу після створення.", "newKnowledge.viewLabel": "Вигляд бази знань", + "newKnowledge.websiteCrawl": "Сканування веб-сайту", "noExternalKnowledge": "API зовнішніх знань поки що не існує, натисніть тут, щоб створити", "parentMode.fullDoc": "Повний документ", "parentMode.paragraph": "Абзац", diff --git a/web/i18n/vi-VN/dataset.json b/web/i18n/vi-VN/dataset.json index ef36bf1d7ef..d3af578caea 100644 --- a/web/i18n/vi-VN/dataset.json +++ b/web/i18n/vi-VN/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "Mô hình xếp hạng lại là cần thiết cho sự kết hợp của các cơ sở kiến thức chất lượng cao và tiết kiệm.", "mixtureInternalAndExternalTip": "Mô hình Rerank là cần thiết cho sự kết hợp giữa kiến thức bên trong và bên ngoài.", "multimodal": "Đa phương thức", + "newKnowledge.actionsColumn": "Hành động", + "newKnowledge.addSource": "Thêm nguồn", + "newKnowledge.addSourceDescription": "Kết nối nguồn với cơ sở kiến thức này — nguồn này tự động đồng bộ hóa và luôn cập nhật.", + "newKnowledge.allSources": "Tất cả các nguồn", "newKnowledge.appsUnavailable": "— ứng dụng", + "newKnowledge.authKind.api-key": "Khóa API", + "newKnowledge.authKind.endpoint": "Điểm cuối", + "newKnowledge.authenticationMethod": "Phương thức xác thực", "newKnowledge.backToList": "Quay lại cơ sở kiến thức", + "newKnowledge.booleanFalse": "Không", + "newKnowledge.booleanTrue": "Có", + "newKnowledge.cancelAddSource": "Hủy", "newKnowledge.cardType": "Không gian kiến thức", + "newKnowledge.configureProvider": "Định cấu hình {{provider}}", + "newKnowledge.connectProvider": "Kết nối {{provider}}", "newKnowledge.connectSource": "Kết nối nguồn", "newKnowledge.connectSourceDescription": "Nội dung luôn được đồng bộ với Notion, trang web và các dịch vụ khác.", + "newKnowledge.connectingProvider": "Đang kết nối…", + "newKnowledge.connectionFailed": "Chúng tôi không thể kết nối {{provider}}. Nhập lại thông tin xác thực và thử lại.", + "newKnowledge.connectionNeedsAttention": "Kết nối {{provider}} cần được chú ý", + "newKnowledge.connectionNeedsAttentionDescription": "Làm mới kết nối trước khi thêm nguồn trang web.", + "newKnowledge.connectionProvisioning": "{{provider}} đang kết nối", + "newKnowledge.connectionRefreshFailed": "Chúng tôi không thể làm mới kết nối này. Hãy thử lại.", + "newKnowledge.crawlSetupUnavailableDescription": "Cấu hình thu thập thông tin trang web bị tắt cho đến khi có quy trình thu thập thông tin.", "newKnowledge.createFailed": "Chúng tôi không thể tạo ra nền tảng kiến thức này. Hãy kiểm tra quyền truy cập của bạn và thử lại.", "newKnowledge.createTitle": "Tạo kiến thức", "newKnowledge.creators": "Người tạo", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "ví dụ. Chính sách hoàn tiền, Câu hỏi thường gặp về vận chuyển và các bước báo cáo — sử dụng cho các câu hỏi hỗ trợ khách hàng", "newKnowledge.detailErrorDescription": "Chúng tôi không thể tải cơ sở kiến thức này. Hãy thử lại.", "newKnowledge.detailErrorTitle": "Đã xảy ra lỗi", + "newKnowledge.disableSource": "Tắt", "newKnowledge.discardDraftConfirm": "Hủy bản nháp", "newKnowledge.discardDraftDescription": "Các thay đổi đối với bản nháp cơ sở kiến thức này sẽ bị mất.", "newKnowledge.discardDraftTitle": "Hủy bản nháp cơ sở kiến thức này?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "Kết nối một nguồn và tài liệu của nguồn đó sẽ luôn được đồng bộ, tự động lập chỉ mục và sẵn sàng sử dụng mà không cần quản lý thiết lập. Các cơ sở kiến thức cũ vẫn hoạt động như trước.", "newKnowledge.guideTitle": "Khám phá Cơ sở kiến thức mới ✨", "newKnowledge.illustrationHeadline": "Kết nối nội dung một lần — mọi ứng dụng sẽ trả lời bằng kiến thức mới nhất.", + "newKnowledge.lastSyncColumn": "Đồng bộ hóa lần cuối", "newKnowledge.learnMore": "Tìm hiểu thêm", "newKnowledge.leavePartialSetupConfirm": "Thoát thiết lập", "newKnowledge.leavePartialSetupDescription": "Cơ sở kiến thức đã được tạo nhưng không thể xác nhận quyền. Nếu thoát, cơ sở kiến thức vẫn được giữ lại; bạn có thể xem lại quyền truy cập sau.", "newKnowledge.leavePartialSetupTitle": "Thoát khỏi thiết lập chưa hoàn tất?", "newKnowledge.legacy": "Cũ", "newKnowledge.loadMore": "Tải thêm", + "newKnowledge.moreProviders": "Xem thêm", "newKnowledge.name": "Tên kiến thức", "newKnowledge.namePlaceholder": "ví dụ: Sổ tay hỗ trợ khách hàng", "newKnowledge.nameRequired": "Nhập tên cơ sở kiến thức.", "newKnowledge.new": "Mới", "newKnowledge.noDescription": "Không có mô tả", + "newKnowledge.noMatchingSources": "Không có nguồn nào phù hợp với tìm kiếm này.", "newKnowledge.notFoundDescription": "Cơ sở kiến thức này có thể đã bị xóa hoặc bạn không có quyền truy cập.", "newKnowledge.notFoundTitle": "Không tìm thấy cơ sở kiến thức", + "newKnowledge.onlineDocuments": "Tài liệu trực tuyến", + "newKnowledge.onlineDrive": "Ổ đĩa trực tuyến", "newKnowledge.permission": "Quyền", "newKnowledge.permissionAllMembers": "Không gian làm việc · tất cả thành viên đều có thể xem và chỉnh sửa", "newKnowledge.permissionOnlyMe": "Chỉ có tôi", "newKnowledge.permissionRestricted": "Quyền không gian làm việc của bạn không cho phép thay đổi cài đặt này.", "newKnowledge.permissionUpdateFailed": "Cơ sở kiến thức đã được tạo nhưng không thể xác nhận quyền. Hãy thử lại để hoàn tất thiết lập.", + "newKnowledge.providerConnected": "Đã kết nối {{provider}}", + "newKnowledge.providerLabel": "Chọn nhà cung cấp", + "newKnowledge.providerLoadFailed": "Nhà cung cấp không thể tải", + "newKnowledge.providerNotConfigured": "{{provider}} chưa được định cấu hình", + "newKnowledge.providerNotConfiguredDescription": "Thêm khóa API hoặc URL điểm cuối để thu thập dữ liệu trang web bằng {{provider}}.", + "newKnowledge.providerUnavailable": "Nhà cung cấp này không có sẵn.", "newKnowledge.readOnlyEmpty": "Yêu cầu biên tập viên không gian làm việc tạo cơ sở kiến thức đầu tiên.", + "newKnowledge.refreshConnectionStatus": "Trạng thái làm mới", + "newKnowledge.refreshingConnection": "Đang làm mới…", + "newKnowledge.removeSource": "Xóa nguồn", + "newKnowledge.retryProviderLoad": "Thử lại", "newKnowledge.routeUnavailable": "Phần này sẽ có sẵn trong bước thiết lập tiếp theo.", + "newKnowledge.searchSources": "Nguồn tìm kiếm", + "newKnowledge.sourceActions": "Hành động dành cho {{name}}", + "newKnowledge.sourceColumn": "Nguồn", + "newKnowledge.sourceFilterLabel": "Lọc nguồn theo trạng thái", + "newKnowledge.sourceStatus.active": "Đang hoạt động", + "newKnowledge.sourceStatus.disabled": "Đã tắt", + "newKnowledge.sourceStatus.error": "Lỗi", + "newKnowledge.sourceStatus.syncing": "Đang đồng bộ hóa", + "newKnowledge.sourceSyncFailed": "Thất bại", + "newKnowledge.sourceType.connector": "Ứng dụng được kết nối", + "newKnowledge.sourceType.object-storage": "Ổ đĩa trực tuyến", + "newKnowledge.sourceType.upload": "Tải lên", + "newKnowledge.sourceType.web": "Thu thập thông tin trang web", + "newKnowledge.sourceTypeLabel": "Loại nguồn", "newKnowledge.sources": "Nguồn", + "newKnowledge.sourcesDescription": "Kiến thức đến từ đâu, nó mới như thế nào và liệu lần đồng bộ hóa cuối cùng có thành công hay không.", + "newKnowledge.sourcesEmptyDescription": "Kết nối trang web, không gian làm việc hoặc ổ đĩa — Dify luôn đồng bộ và cập nhật nội dung để việc truy xuất không bao giờ bị gián đoạn.", + "newKnowledge.sourcesEmptyTitle": "Chưa có nguồn nào được kết nối", + "newKnowledge.sourcesErrorDescription": "Chúng tôi không thể tải nguồn. Hãy thử lại.", + "newKnowledge.sourcesErrorTitle": "Không thể tải nguồn", "newKnowledge.startEmpty": "Bắt đầu trống", "newKnowledge.startEmptyDescription": "Tạo ngay bây giờ và thêm nội dung sau.", "newKnowledge.startWith": "Bắt đầu với", "newKnowledge.startWithHelp": "Bạn có thể thêm nhiều Nguồn hoặc Tài liệu hơn bất cứ lúc nào.", + "newKnowledge.statusColumn": "Trạng thái", + "newKnowledge.syncNow": "Đồng bộ hóa ngay", + "newKnowledge.syncPolicyColumn": "Chính sách đồng bộ hóa", "newKnowledge.tags": "Thẻ", "newKnowledge.unavailableDescription": "KnowledgeFS hiện không khả dụng cho không gian làm việc này.", "newKnowledge.unavailableTitle": "Kiến thức mới không khả dụng", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "Tải tệp lên", "newKnowledge.uploadFilesDescription": "Thêm tệp từ máy tính — tệp sẽ được lập chỉ mục ngay khi tạo.", "newKnowledge.viewLabel": "Chế độ xem kiến thức", + "newKnowledge.websiteCrawl": "Thu thập thông tin trang web", "noExternalKnowledge": "Chưa có API Kiến thức Bên ngoài, hãy nhấp vào đây để tạo", "parentMode.fullDoc": "Tài liệu đầy đủ", "parentMode.paragraph": "Đoạn", diff --git a/web/i18n/zh-Hans/dataset.json b/web/i18n/zh-Hans/dataset.json index 8d74fa7d286..0bf383dc13b 100644 --- a/web/i18n/zh-Hans/dataset.json +++ b/web/i18n/zh-Hans/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "混合使用高质量和经济型知识库需要配置 Rerank 模型。", "mixtureInternalAndExternalTip": "混合使用内部和外部知识时需要配置 Rerank 模型。", "multimodal": "多模态", + "newKnowledge.actionsColumn": "行动", + "newKnowledge.addSource": "添加来源", + "newKnowledge.addSourceDescription": "将来源连接到该知识库 - 它会自动同步并保持最新。", + "newKnowledge.allSources": "所有来源", "newKnowledge.appsUnavailable": "— 个应用", + "newKnowledge.authKind.api-key": "API 密钥", + "newKnowledge.authKind.endpoint": "端点", + "newKnowledge.authenticationMethod": "认证方式", "newKnowledge.backToList": "返回知识库列表", + "newKnowledge.booleanFalse": "否", + "newKnowledge.booleanTrue": "是的", + "newKnowledge.cancelAddSource": "取消", "newKnowledge.cardType": "知识空间", + "newKnowledge.configureProvider": "配置{{provider}}", + "newKnowledge.connectProvider": "连接{{provider}}", "newKnowledge.connectSource": "连接数据源", "newKnowledge.connectSourceDescription": "内容会与 Notion、网站及其他服务保持同步。", + "newKnowledge.connectingProvider": "正在连接...", + "newKnowledge.connectionFailed": "我们无法连接 {{provider}}。重新输入凭据并重试。", + "newKnowledge.connectionNeedsAttention": "{{provider}}连接需要注意", + "newKnowledge.connectionNeedsAttentionDescription": "添加网站源之前刷新连接。", + "newKnowledge.connectionProvisioning": "{{provider}} 正在连接", + "newKnowledge.connectionRefreshFailed": "我们无法刷新此连接。再试一次。", + "newKnowledge.crawlSetupUnavailableDescription": "在爬网工作流程可用之前,网站爬网配置将被禁用。", "newKnowledge.createFailed": "无法创建此知识库,请检查权限后重试。", "newKnowledge.createTitle": "创建知识库", "newKnowledge.creators": "创建者", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "例如:退款政策、配送常见问题和升级处理步骤——用于客户支持问题", "newKnowledge.detailErrorDescription": "无法加载此知识库,请重试。", "newKnowledge.detailErrorTitle": "出现错误", + "newKnowledge.disableSource": "禁用", "newKnowledge.discardDraftConfirm": "放弃草稿", "newKnowledge.discardDraftDescription": "对此知识库草稿的更改将会丢失。", "newKnowledge.discardDraftTitle": "放弃此知识库草稿?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "连接数据源后,其文档会保持同步、自动建立索引并可立即使用,无需管理任何配置。旧版知识库仍会照常运行。", "newKnowledge.guideTitle": "认识全新的知识库 ✨", "newKnowledge.illustrationHeadline": "只需连接一次内容,每个应用都能基于最新知识回答。", + "newKnowledge.lastSyncColumn": "上次同步", "newKnowledge.learnMore": "了解更多", "newKnowledge.leavePartialSetupConfirm": "离开设置", "newKnowledge.leavePartialSetupDescription": "知识库已创建,但无法确认其权限状态。离开后知识库仍会保留,你可以稍后检查访问权限。", "newKnowledge.leavePartialSetupTitle": "离开未完成的设置?", "newKnowledge.legacy": "旧版", "newKnowledge.loadMore": "加载更多", + "newKnowledge.moreProviders": "更多提供商", "newKnowledge.name": "知识库名称", "newKnowledge.namePlaceholder": "例如:客户支持手册", "newKnowledge.nameRequired": "请输入知识库名称。", "newKnowledge.new": "新版", "newKnowledge.noDescription": "暂无描述", + "newKnowledge.noMatchingSources": "没有与此搜索匹配的来源。", "newKnowledge.notFoundDescription": "此知识库可能已被删除,或你没有访问权限。", "newKnowledge.notFoundTitle": "未找到知识库", + "newKnowledge.onlineDocuments": "在线文档", + "newKnowledge.onlineDrive": "在线驱动器", "newKnowledge.permission": "权限", "newKnowledge.permissionAllMembers": "工作区 · 所有成员均可查看和编辑", "newKnowledge.permissionOnlyMe": "仅自己", "newKnowledge.permissionRestricted": "你的工作区权限不允许更改此设置。", "newKnowledge.permissionUpdateFailed": "知识库已创建,但无法确认其权限状态。请重试以完成设置。", + "newKnowledge.providerConnected": "{{provider}}已连接", + "newKnowledge.providerLabel": "提供商", + "newKnowledge.providerLoadFailed": "提供商无法加载", + "newKnowledge.providerNotConfigured": "{{provider}} 未配置", + "newKnowledge.providerNotConfiguredDescription": "添加 API 密钥或端点 URL 以使用 {{provider}} 抓取网站。", + "newKnowledge.providerUnavailable": "该提供商不可用。", "newKnowledge.readOnlyEmpty": "请联系工作区编辑者创建第一个知识库。", + "newKnowledge.refreshConnectionStatus": "刷新状态", + "newKnowledge.refreshingConnection": "正在刷新……", + "newKnowledge.removeSource": "删除来源", + "newKnowledge.retryProviderLoad": "重试", "newKnowledge.routeUnavailable": "此部分将在下一设置步骤中开放。", + "newKnowledge.searchSources": "搜索来源", + "newKnowledge.sourceActions": "{{name}} 的操作", + "newKnowledge.sourceColumn": "来源", + "newKnowledge.sourceFilterLabel": "按状态过滤源", + "newKnowledge.sourceStatus.active": "活跃", + "newKnowledge.sourceStatus.disabled": "已禁用", + "newKnowledge.sourceStatus.error": "错误", + "newKnowledge.sourceStatus.syncing": "正在同步", + "newKnowledge.sourceSyncFailed": "失败", + "newKnowledge.sourceType.connector": "连接的应用程序", + "newKnowledge.sourceType.object-storage": "在线驱动器", + "newKnowledge.sourceType.upload": "上传", + "newKnowledge.sourceType.web": "网站抓取", + "newKnowledge.sourceTypeLabel": "源类型", "newKnowledge.sources": "数据源", + "newKnowledge.sourcesDescription": "知识从哪里来,新鲜程度如何,上次同步是否成功。", + "newKnowledge.sourcesEmptyDescription": "连接网站、工作空间或云盘——Dify 会持续保持同步和更新,确保检索始终稳定。", + "newKnowledge.sourcesEmptyTitle": "尚未连接来源", + "newKnowledge.sourcesErrorDescription": "我们无法加载源。再试一次。", + "newKnowledge.sourcesErrorTitle": "来源无法加载", "newKnowledge.startEmpty": "从空白开始", "newKnowledge.startEmptyDescription": "现在创建,稍后再添加内容。", "newKnowledge.startWith": "创建方式", "newKnowledge.startWithHelp": "你可以随时添加更多数据源或文档。", + "newKnowledge.statusColumn": "状态", + "newKnowledge.syncNow": "立即同步", + "newKnowledge.syncPolicyColumn": "同步策略", "newKnowledge.tags": "标签", "newKnowledge.unavailableDescription": "KnowledgeFS 当前在此工作区不可用。", "newKnowledge.unavailableTitle": "新版知识库不可用", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "上传文件", "newKnowledge.uploadFilesDescription": "从电脑添加文件,创建后会立即建立索引。", "newKnowledge.viewLabel": "知识库视图", + "newKnowledge.websiteCrawl": "网站抓取", "noExternalKnowledge": "还没有外部知识库 API,点击此处创建", "parentMode.fullDoc": "全文", "parentMode.paragraph": "段落", diff --git a/web/i18n/zh-Hant/dataset.json b/web/i18n/zh-Hant/dataset.json index bdfbff544c3..40462af97a9 100644 --- a/web/i18n/zh-Hant/dataset.json +++ b/web/i18n/zh-Hant/dataset.json @@ -131,11 +131,30 @@ "mixtureHighQualityAndEconomicTip": "混合高品質和經濟知識庫需要重新排序模型。", "mixtureInternalAndExternalTip": "Rerank 模型是內部和外部知識的混合所必需的。", "multimodal": "多模態", + "newKnowledge.actionsColumn": "行動", + "newKnowledge.addSource": "新增來源", + "newKnowledge.addSourceDescription": "將來源連接到該知識庫 - 它會自動同步並保持最新。", + "newKnowledge.allSources": "所有來源", "newKnowledge.appsUnavailable": "— 個應用程式", + "newKnowledge.authKind.api-key": "API 金鑰", + "newKnowledge.authKind.endpoint": "端點", + "newKnowledge.authenticationMethod": "認證方式", "newKnowledge.backToList": "返回知識庫列表", + "newKnowledge.booleanFalse": "否", + "newKnowledge.booleanTrue": "是的", + "newKnowledge.cancelAddSource": "取消", "newKnowledge.cardType": "知識空間", + "newKnowledge.configureProvider": "配置{{provider}}", + "newKnowledge.connectProvider": "連接{{provider}}", "newKnowledge.connectSource": "連接資料來源", "newKnowledge.connectSourceDescription": "內容會與 Notion、網站及其他服務保持同步。", + "newKnowledge.connectingProvider": "正在連接...", + "newKnowledge.connectionFailed": "我們無法連接 {{provider}}。重新輸入憑證並重試。", + "newKnowledge.connectionNeedsAttention": "{{provider}}連接需要注意", + "newKnowledge.connectionNeedsAttentionDescription": "新增網站來源之前刷新連線。", + "newKnowledge.connectionProvisioning": "{{provider}} 正在連接", + "newKnowledge.connectionRefreshFailed": "我們無法刷新此連線。再試一次。", + "newKnowledge.crawlSetupUnavailableDescription": "在爬網工作流程可用之前,網站爬網設定將會被停用。", "newKnowledge.createFailed": "無法建立此知識庫,請檢查權限後再試一次。", "newKnowledge.createTitle": "建立知識庫", "newKnowledge.creators": "建立者", @@ -144,6 +163,7 @@ "newKnowledge.descriptionPlaceholder": "例如:退款政策、配送常見問題和升級處理步驟——用於客戶支援問題", "newKnowledge.detailErrorDescription": "無法載入此知識庫,請再試一次。", "newKnowledge.detailErrorTitle": "發生錯誤", + "newKnowledge.disableSource": "停用", "newKnowledge.discardDraftConfirm": "放棄草稿", "newKnowledge.discardDraftDescription": "對此知識庫草稿的變更將會遺失。", "newKnowledge.discardDraftTitle": "放棄此知識庫草稿?", @@ -158,31 +178,68 @@ "newKnowledge.guideDescription": "連接資料來源後,其文件會保持同步、自動建立索引並可立即使用,無需管理任何設定。舊版知識庫仍會照常運作。", "newKnowledge.guideTitle": "認識全新的知識庫 ✨", "newKnowledge.illustrationHeadline": "只需連接一次內容,每個應用程式都能以最新知識回答。", + "newKnowledge.lastSyncColumn": "上次同步", "newKnowledge.learnMore": "瞭解更多", "newKnowledge.leavePartialSetupConfirm": "離開設定", "newKnowledge.leavePartialSetupDescription": "知識庫已建立,但無法確認其權限狀態。離開後知識庫仍會保留,你可以稍後檢查存取權限。", "newKnowledge.leavePartialSetupTitle": "離開未完成的設定?", "newKnowledge.legacy": "舊版", "newKnowledge.loadMore": "載入更多", + "newKnowledge.moreProviders": "更多供應商", "newKnowledge.name": "知識庫名稱", "newKnowledge.namePlaceholder": "例如:客戶支援手冊", "newKnowledge.nameRequired": "請輸入知識庫名稱。", "newKnowledge.new": "新版", "newKnowledge.noDescription": "暫無描述", + "newKnowledge.noMatchingSources": "沒有與此搜尋相符的來源。", "newKnowledge.notFoundDescription": "此知識庫可能已被刪除,或你沒有存取權限。", "newKnowledge.notFoundTitle": "找不到知識庫", + "newKnowledge.onlineDocuments": "線上文檔", + "newKnowledge.onlineDrive": "線上驅動器", "newKnowledge.permission": "權限", "newKnowledge.permissionAllMembers": "工作區 · 所有成員皆可檢視和編輯", "newKnowledge.permissionOnlyMe": "僅自己", "newKnowledge.permissionRestricted": "你的工作區權限不允許變更此設定。", "newKnowledge.permissionUpdateFailed": "知識庫已建立,但無法確認其權限狀態。請重試以完成設定。", + "newKnowledge.providerConnected": "{{provider}}已連接", + "newKnowledge.providerLabel": "供應商", + "newKnowledge.providerLoadFailed": "提供者無法載入", + "newKnowledge.providerNotConfigured": "{{provider}} 未配置", + "newKnowledge.providerNotConfiguredDescription": "新增 API 金鑰或端點 URL 以使用 {{provider}} 抓取網站。", + "newKnowledge.providerUnavailable": "該提供者不可用。", "newKnowledge.readOnlyEmpty": "請聯絡工作區編輯者建立第一個知識庫。", + "newKnowledge.refreshConnectionStatus": "刷新狀態", + "newKnowledge.refreshingConnection": "正在重新整理…", + "newKnowledge.removeSource": "刪除來源", + "newKnowledge.retryProviderLoad": "重試", "newKnowledge.routeUnavailable": "此區段將在下一個設定步驟中開放。", + "newKnowledge.searchSources": "搜尋來源", + "newKnowledge.sourceActions": "{{name}} 的操作", + "newKnowledge.sourceColumn": "來源", + "newKnowledge.sourceFilterLabel": "按狀態過濾來源", + "newKnowledge.sourceStatus.active": "活躍", + "newKnowledge.sourceStatus.disabled": "已停用", + "newKnowledge.sourceStatus.error": "錯誤", + "newKnowledge.sourceStatus.syncing": "正在同步", + "newKnowledge.sourceSyncFailed": "失敗", + "newKnowledge.sourceType.connector": "連接的應用程式", + "newKnowledge.sourceType.object-storage": "線上驅動器", + "newKnowledge.sourceType.upload": "上傳", + "newKnowledge.sourceType.web": "網站抓取", + "newKnowledge.sourceTypeLabel": "來源類型", "newKnowledge.sources": "資料來源", + "newKnowledge.sourcesDescription": "知識從哪裡來,新鮮程度如何,上次同步是否成功。", + "newKnowledge.sourcesEmptyDescription": "連接網站、工作空間或雲端硬碟——Dify 會持續保持同步和更新,確保檢索始終穩定。", + "newKnowledge.sourcesEmptyTitle": "尚未連接來源", + "newKnowledge.sourcesErrorDescription": "我們無法載入來源。再試一次。", + "newKnowledge.sourcesErrorTitle": "來源無法載入", "newKnowledge.startEmpty": "從空白開始", "newKnowledge.startEmptyDescription": "現在建立,稍後再加入內容。", "newKnowledge.startWith": "建立方式", "newKnowledge.startWithHelp": "你可以隨時新增更多資料來源或文件。", + "newKnowledge.statusColumn": "狀態", + "newKnowledge.syncNow": "立即同步", + "newKnowledge.syncPolicyColumn": "同步策略", "newKnowledge.tags": "標籤", "newKnowledge.unavailableDescription": "KnowledgeFS 目前在此工作區不可用。", "newKnowledge.unavailableTitle": "新版知識庫不可用", @@ -190,6 +247,7 @@ "newKnowledge.uploadFiles": "上傳檔案", "newKnowledge.uploadFilesDescription": "從電腦加入檔案,建立後會立即建立索引。", "newKnowledge.viewLabel": "知識庫檢視", + "newKnowledge.websiteCrawl": "網站抓取", "noExternalKnowledge": "目前還沒有外部知識 API,按兩下此處創建", "parentMode.fullDoc": "完整文件", "parentMode.paragraph": "段",