diff --git a/e2e/smoke.spec.ts b/e2e/smoke.spec.ts index d7a0a21..c9baa04 100644 --- a/e2e/smoke.spec.ts +++ b/e2e/smoke.spec.ts @@ -7,11 +7,14 @@ test.beforeEach(async ({ page }) => { }); }); -test('creates a new flow and adds an extra tab', async ({ page }) => { +async function openHomeDashboard(page: import('@playwright/test').Page) { await page.goto('/#/home'); + await expect(page.getByTestId('home-create-new-main')).toBeVisible({ timeout: 15000 }); +} - await expect(page.getByTestId('home-create-new')).toBeVisible(); - await page.getByTestId('home-create-new').click(); +test('creates a new flow and adds an extra tab', async ({ page }) => { + await openHomeDashboard(page); + await page.getByTestId('home-create-new-main').click(); await expect(page).toHaveURL(/#\/flow\/[^?]+(?:\?.*)?$/); await expect(page.getByTestId('toolbar-add-toggle')).toBeVisible({ timeout: 15000 }); @@ -27,8 +30,8 @@ test('creates a new flow and adds an extra tab', async ({ page }) => { }); test('saves and restores snapshot state', async ({ page }) => { - await page.goto('/#/home'); - await page.getByTestId('home-create-new').click(); + await openHomeDashboard(page); + await page.getByTestId('home-create-new-main').click(); await expect(page.getByTestId('toolbar-add-toggle')).toBeVisible({ timeout: 15000 }); await expect(page.getByTestId('topnav-menu-toggle')).toBeVisible({ timeout: 15000 }); diff --git a/e2e/workflows.spec.ts b/e2e/workflows.spec.ts index bbeec2e..80fee72 100644 --- a/e2e/workflows.spec.ts +++ b/e2e/workflows.spec.ts @@ -13,7 +13,8 @@ test.beforeEach(async ({ page }) => { async function createNewFlow(page: import('@playwright/test').Page) { await page.goto('/#/home'); - await page.getByTestId('home-create-new').click(); + await expect(page.getByTestId('home-create-new-main')).toBeVisible({ timeout: 15000 }); + await page.getByTestId('home-create-new-main').click(); await expect(page).toHaveURL(/#\/flow\/[^?]+(?:\?.*)?$/); await expect(page.getByTestId('toolbar-add-toggle')).toBeVisible({ timeout: 15000 }); await expect(page.getByTestId('flow-page-tab').first()).toBeVisible(); @@ -198,14 +199,14 @@ test('command bar opens with Cmd+K', async ({ page }) => { await createNewFlow(page); await page.keyboard.press('ControlOrMeta+k'); - await expect(page.getByPlaceholder(/search/i)).toBeVisible(); + await expect(page.getByRole('combobox', { name: /search command bar actions/i })).toBeVisible(); }); test('command bar fuzzy search works', async ({ page }) => { await createNewFlow(page); await page.keyboard.press('ControlOrMeta+k'); - await page.getByPlaceholder(/search/i).fill('arc'); + await page.getByRole('combobox', { name: /search command bar actions/i }).fill('arc'); await expect(page.getByText(/architecture/i).first()).toBeVisible(); }); diff --git a/package.json b/package.json index ee52a0b..67e7dec 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "scripts": { "dev": "vite", "build": "node scripts/generate-sitemap.js && tsc -b && vite build", + "build:analyze": "npm run build && node scripts/analyze-bundle.mjs", "bundle:check": "node scripts/check-bundle-budget.mjs", "build:ci": "npm run build && npm run bundle:check", "test:ci": "npm run test -- --run && npm run build:ci", @@ -31,8 +32,8 @@ "build:lib": "vite build -c vite.lib.config.ts", "build:lib:watch": "vite build -c vite.lib.config.ts --watch", "lint": "eslint . --ext ts,tsx --ignore-pattern 'web/**' --ignore-pattern 'docs-site/**' --report-unused-disable-directives --max-warnings 0", - "build:web": "npm run build --workspace=web", - "build:docs": "npm run build --workspace=docs-site", + "build:web": "pnpm --filter openflowkit-web build", + "build:docs": "pnpm --filter openflowkit-docs build", "bench:harness": "node scripts/benchmark-harness.mjs", "bench:summary": "node scripts/benchmark-summary.mjs", "bench:check": "node scripts/check-benchmark-results.mjs", @@ -44,7 +45,6 @@ }, "dependencies": { "@google/genai": "^1.40.0", - "@types/react-syntax-highlighter": "^15.5.13", "@xyflow/react": "^12.10.1", "elkjs": "^0.11.0", "framer-motion": "^12.34.0", @@ -66,7 +66,6 @@ "remark-gfm": "4.0.0", "y-indexeddb": "^9.0.12", "y-webrtc": "^10.3.0", - "y-websocket": "^3.0.0", "yjs": "^13.6.29", "zustand": "^5.0.11" }, @@ -76,6 +75,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@types/node": "^22.14.0", + "@types/react-syntax-highlighter": "^15.5.13", "@typescript-eslint/eslint-plugin": "^8.55.0", "@typescript-eslint/parser": "^8.55.0", "@vitejs/plugin-react": "^5.1.4", diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..0abf882 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - web + - docs-site diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 205020e..2a425cc 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -141,12 +141,14 @@ "gif": "Wiedergabe-GIF", "hintPlaybackGif": "Kurze Schleife für Doku/Social", "share": "Live-Canvas teilen", + "shareEmbed": "Teilen & Einbetten", "hintShareViewer": "Einladungslink für diesen Raum", + "hintShareEmbed": "Nur-Lese-Link für Viewer", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "Video", + "sectionCode": "Code", "shareSection": "Canvas teilen", "revealVideo": "Reveal Video", "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", @@ -240,6 +242,7 @@ } }, "home": { + "appName": "OpenFlowKit", "title": "Dashboard", "description": "Verwalten Sie Ihre Flüsse und Diagramme.", "recentFiles": "Letzte Dateien", @@ -263,7 +266,22 @@ "confirmation": "\"{{name}}\" löschen?", "hint": "Dies kann nicht rückgängig gemacht werden, es sei denn, Sie haben ein exportiertes Backup oder eine weitere Kopie.", "closeDialog": "Dialog zum Löschen des Flows schließen" - } + }, + "suggestionBlank": "Leere Leinwand", + "suggestionBlankDesc": "Direkt in den Editor einsteigen", + "suggestionAI": "Flowpilot KI", + "suggestionAIDesc": "Mit einer Eingabe beginnen", + "suggestionImport": "Importieren", + "suggestionImportDesc": "Bestehende Arbeit einbringen", + "suggestionTemplates": "Vorlagen", + "suggestionTemplatesDesc": "Mit einem bewährten Muster beginnen", + "continueTitle": "Mit einer kürzlichen Aktion fortfahren", + "homeEmptyTitle": "Erstellen Sie Ihren ersten Flow", + "homeEmptySubtitle": "Entwerfen Sie sofort Enterprise-Architekturen. Beginnen Sie mit einer leeren Leinwand, beschreiben Sie Ihre Infrastruktur mit unserem KI-Builder oder verwenden Sie eine maßgeschneiderte Vorlage.", + "homeBlankCanvas": "Leere Leinwand", + "homeFlowpilotAI": "Flowpilot KI", + "homeTemplates": "Vorlagen", + "homeImportFile": "Oder eine bestehende Datei importieren" }, "settings": { "title": "Einstellungen", @@ -295,33 +313,29 @@ "help": "Hilfe" }, "properties": { - "title": "Eigenschaften", - "nodeType": "Knotentyp", - "label": "Bezeichnung", - "description": "Beschreibung", - "color": "Farbe", - "icon": "Symbol", - "size": "Größe", - "shape": "Form", - "bulkShape": "Mehrere Formen", - "bulkColor": "Mehrere Farben", - "bulkIcon": "Mehrere Symbole", - "labelTransform": "Text-Transformation", - "prefixOptional": "Präfix (optional)", + "title": "Properties", + "shape": "Shape", + "color": "Color", + "icon": "Icon", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", + "bulkShape": "Bulk Shape", + "bulkColor": "Bulk Color", + "bulkIcon": "Bulk Icon", + "labelTransform": "Label Transform", + "findReplace": "Find & Replace", + "findLabel": "Find", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", "suffixOptional": "Suffix (optional)", - "findReplace": "Suchen und Ersetzen", - "findLabel": "Suchen", - "findPlaceholder": "Zu suchender Text", - "replaceLabel": "Ersetzen durch", - "replacePlaceholder": "Ersetzungstext", - "useRegex": "Regulären Ausdruck verwenden", - "previewSummary": "Vorschau", - "bulkApplySummary": "{{count}} ausgewählte Elemente werden aktualisiert", - "selectFieldToApply": "Wählen Sie mindestens ein Feld zum Anwenden aus.", - "applyToSelectedNodes": "Auf ausgewählte Elemente anwenden", - "imageSettings": "Bildeinstellungen", - "transparency": "Transparenz", - "rotation": "Drehung" + "useRegex": "Use Regex", + "applyToSelectedNodes": "Apply to selected nodes", + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "Auswahlübersicht" }, "saveStatus": { "saved": "Gespeichert" @@ -346,7 +360,9 @@ "title": "Verlauf", "undo": "Rückgängig", "redo": "Wiederholen", - "clear": "Verlauf löschen" + "clear": "Verlauf löschen", + "undoUnavailable": "Noch nichts rückgängig zu machen.", + "redoUnavailable": "Im Moment nichts zu wiederholen." }, "errors": { "generic": "Etwas ist schiefgelaufen", @@ -378,7 +394,12 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", - "getStarted": "Get Started" + "getStarted": "Get Started", + "shortcutCommandBar": "Befehlszentrale öffnen", + "shortcutHelp": "Tastenkürzel anzeigen", + "shortcutCanvas": "Knoten auf Leinwand hinzufügen", + "shortcutsTitle": "Schnellstart mit Tastenkürzeln", + "shortcutsBadge": "Tastatur zuerst" }, "footer": { "mitLicensed": "MIT-Lizenz" @@ -653,7 +674,7 @@ "strokeWidth": "Strichbreite", "largeGraphSafety": "Große-Graph-Schutz", "largeGraphSafetyAuto": "Automatisch", - "largeGraphSafetyOn": "Ein", + "largeGraphSafetyOn": "Großgraph-Sicherheit An", "largeGraphSafetyOff": "Aus", "exportModeDeterministic": "Deterministisch", "exportModeLegacy": "Legacy", @@ -712,11 +733,12 @@ "sql": "Füge hier CREATE-TABLE-Anweisungen ein...", "infra": "Füge hier Terraform-State-JSON, Kubernetes-YAML, Docker Compose oder Terraform-HCL ein...", "openapi": "Füge hier dein OpenAPI-/Swagger-YAML oder -JSON ein...", - "code": "Füge hier deinen Quellcode ein..." + "code": "Füge hier deinen Quellcode ein...", + "mermaid": "Füge hier Mermaid-Diagrammcode ein..." }, "infraFormats": { - "terraformState": "Terraform-State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "Terraform-Zustand", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", "terraformHcl": "Terraform HCL (AI)" }, @@ -735,13 +757,16 @@ "infra": "Infra", "openapi": "OpenAPI", "code": "Code", - "codebase": "Repository" + "codebase": "Repository", + "mindmap": "Mindmap", + "markdown": "Markdown" }, "title": "Aus Daten importieren", "description": "Importiere Code, Infrastruktur, SQL oder API-Spezifikationen in dein Diagramm.", "uploadFile": "Datei hochladen", "parsing": "Wird geparst...", "parse": "Parsen", + "parseNativeProject": "Generate Native Diagram", "analyzing": "Wird analysiert...", "aiActions": { "generateErd": "ERD generieren (KI)", @@ -793,33 +818,31 @@ "title": "Einstellungen", "general": "Allgemein", "flowpilotAI": "Flowpilot", - "shortcuts": "Kürzel", + "shortcuts": "Tastenkürzel", "running": "{appName} wird ausgeführt", "generalSettings": "Allgemeine Einstellungen", "flowpilotConfigurations": "Flowpilot-Konfiguration", "keyboardShortcuts": "Tastaturkürzel", "canvas": { "title": "Canvas", - "showGrid": "Raster anzeigen", - "showGridDesc": "Punktraster auf dem Canvas", - "snapToGrid": "Am Raster ausrichten", - "snapToGridDesc": "Knoten beim Bewegen einrasten", - "miniMap": "Minimap", - "miniMapDesc": "Minimap unten rechts", - "architectureStrictMode": "Architektur-Strict-Mode", - "architectureStrictModeDesc": "Blockiert den Mermaid-Import, wenn Architekturdiagnosen Wiederherstellungs-/Validierungsprobleme enthalten", - "alignmentGuides": "Ausrichtungshilfen", - "alignmentGuidesDesc": "Zeigt intelligente Hilfslinien beim Ziehen von Knoten", - "routingProfile": "Routing-Profil", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", + "routingProfile": "Routing Profile", "routingProfileStandard": "Standard", "routingProfileInfrastructure": "Infrastruktur", "routingProfileHint": "Der Infrastrukturmodus bevorzugt orthogonale Routen für Servicediagramme.", - "edgeBundling": "Parallele Kanten bündeln", - "edgeBundlingDesc": "Parallele Verbindungen auf gemeinsamen Spuren halten" + "edgeBundling": "Geschwisterkanten bündeln", + "edgeBundlingDesc": "Parallele Verbindungen auf gemeinsamen Spuren halten", + "architectureStrictMode": "Architektur-Strict-Modus", + "architectureStrictModeDesc": "Mermaid-Import blockieren, wenn Architekturdiagnosen Wiederherstellungs-/Validierungsprobleme enthalten" }, "ai": { "provider": "Anbieter", - "model": "Modell", + "model": "KI-Modell", "apiKey": "API-Schlüssel", "customBaseUrl": "Benutzerdefinierte Basis-URL", "optional": "Optional", @@ -886,6 +909,135 @@ "browserFriendly": "Browser-tauglich", "proxyLikely": "Proxy wahrscheinlich", "mixed": "Abhängig vom Endpunkt" + }, + "models": { + "gemini": { + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } + }, + "gemini-3-flash": { + "label": "Gemini 3 Flash" + }, + "gemini-3-pro": { + "label": "Gemini 3 Pro" + } + }, + "openai": { + "gpt-5-mini": { + "label": "GPT-5 Mini" + }, + "gpt-5": { + "2": { + "label": "GPT-5.2" + }, + "label": "GPT-5" + }, + "o4-mini": { + "label": "O4-Mini" + }, + "o3": { + "label": "O3" + } + }, + "claude": { + "claude-haiku-4-5": { + "label": "Claude Haiku 4.5" + }, + "claude-sonnet-4-5": { + "label": "Claude Sonnet 4.5" + }, + "claude-sonnet-4-6": { + "label": "Claude Sonnet 4.6" + }, + "claude-opus-4-6": { + "label": "Claude Opus 4.6" + } + }, + "groq": { + "meta-llama/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "meta-llama/llama-4-maverick-17b-128e-instruct": { + "label": "Llama 4 Maverick" + }, + "qwen/qwen3-32b": { + "label": "Qwen 3 32B" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } + } + }, + "nvidia": { + "meta/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "nvidia/nemotron-nano-12b-v2-vl": { + "label": "Nemotron Nano 12B" + }, + "deepseek/deepseek-v3-2": { + "label": "DeepSeek V3-2" + }, + "qwen/qwq-32b": { + "label": "QwQ 32B" + }, + "moonshotai/kimi-k2-thinking": { + "label": "Kimi K2 Thinking" + } + }, + "cerebras": { + "gpt-oss-120b": { + "label": "GPT OSS 120B" + }, + "qwen-3-32b": { + "label": "Qwen 3 32B" + }, + "qwen-3-235b-a22b": { + "label": "Qwen 3 235B" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } + } + }, + "mistral": { + "mistral-small-latest": { + "label": "Mistral Small" + }, + "mistral-medium-latest": { + "label": "Mistral Medium" + }, + "mistral-large-latest": { + "label": "Mistral Large" + }, + "codestral-latest": { + "label": "Codestral" + }, + "pixtral-large-latest": { + "label": "Pixtral Large" + } + } + }, + "customEndpoints": { + "ollama": { + "name": "Ollama" + }, + "lmStudio": { + "name": "LM Studio" + }, + "together": { + "name": "Together AI" + } } }, "brand": { @@ -926,7 +1078,19 @@ "analytics": { "enableTitle": "Anonyme Start-Analysen", "enableDescription": "Anonyme grundlegende Nutzungsdaten teilen (optional)" - } + }, + "search": "Suchen...", + "appearance": "Erscheinungsbild", + "account": "Konto", + "about": "Über", + "language": "Sprache", + "theme": "Design", + "fontSize": "Schriftgröße", + "fontFamily": "Schriftart", + "save": "Speichern", + "cancel": "Abbrechen", + "reset": "Zurücksetzen", + "confirm": "Bestätigen" }, "customNodes": { "browserContent": "Browser-Inhalt", @@ -995,7 +1159,8 @@ "note": "Haftnotiz", "noteDesc": "Dokumentation", "releaseToConnect": "Loslassen zum Verbinden", - "close": "Verbindungsmenü schließen" + "close": "Verbindungsmenü schließen", + "label": "Knotenverbindungsmenü" }, "errorBoundary": { "title": "Etwas ist schiefgelaufen", @@ -1024,7 +1189,12 @@ "namedVersions": "Benannte Versionen", "noNamedSnapshots": "Noch keine benannten Versionen.", "autosavedVersions": "Automatisch gespeicherte Prüfpunkte", - "noAutoSnapshots": "Noch keine automatisch gespeicherten Prüfpunkte." + "noAutoSnapshots": "Noch keine automatisch gespeicherten Prüfpunkte.", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "Flow-Vorlagen", @@ -1052,31 +1222,6 @@ "noSelection": "Nichts ausgewählt", "selectHint": "Klicken Sie auf einen Knoten oder eine Kante, um deren Eigenschaften zu bearbeiten" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "Auswahlübersicht" - }, "flowCanvas": { "strictModePasteBlocked": "Der Architektur-Strict-Mode hat das Mermaid-Einfügen blockiert. Öffnen Sie die Code-Ansicht, beheben Sie die Diagnosen und versuchen Sie es erneut." }, @@ -1106,9 +1251,9 @@ }, "share": { "close": "Close", - "title": "Design teilen", + "title": "Teilen", "betaBadge": "Beta", - "description": "Laden Sie Mitwirkende ein, diesen Flow gemeinsam mit Ihnen in Echtzeit anzusehen und zu bearbeiten.", + "description": "Diese Leinwand teilen", "roomId": "Raum-ID", "link": "Freigabelink", "copied": "Copied Link!", @@ -1132,7 +1277,20 @@ "copyFailed": "Freigabelink konnte nicht kopiert werden.", "linkCopied": "Zusammenarbeitslink wurde kopiert.", "copyManual": "Der Zugriff auf die Zwischenablage ist blockiert. Kopieren Sie den Link manuell aus dem Freigabedialog." - } + }, + "embed": "Einbetten", + "embedCode": "Einbettungscode", + "export": "Exportieren", + "settings": "Freigabeeinstellungen", + "anyoneWithLink": "Jeder mit Link", + "viewOnly": "Nur ansehen", + "canEdit": "Kann bearbeiten", + "disable": "Freigabe deaktivieren", + "enable": "Freigabe aktivieren", + "invite": "Einladen", + "pending": "Ausstehend", + "revoke": "Widerrufen", + "expired": "Abgelaufen" }, "connectionPanel": { "architecture": "Architektur", @@ -1144,6 +1302,65 @@ "deleteConnection": "Verbindung löschen" }, "sidebar": { - "close": "Seitenleiste schließen" + "close": "Seitenleiste schließen", + "searchPlaceholder": "Suchen...", + "noResults": "Keine Ergebnisse", + "nodes": "Knoten", + "components": "Komponenten", + "snippets": "Snippets", + "addons": "Add-ons" + }, + "contextMenu": { + "label": "Canvas-Kontextmenü" + }, + "canvas": { + "addNodeShortcut": "Knoten hinzufügen", + "aiChatPlaceholder": "Etwas erstellen...", + "nodes": "Knoten", + "connections": "Verbindungen", + "elements": "Elemente", + "selection": "Auswahl", + "noSelection": "Keine Auswahl", + "alignNodes": "Knoten ausrichten", + "distributeNodes": "Knoten verteilen", + "alignLeft": "Links ausrichten", + "alignCenter": "Zentriert ausrichten", + "alignRight": "Rechts ausrichten", + "alignTop": "Oben ausrichten", + "alignMiddle": "Mitte ausrichten", + "alignBottom": "Unten ausrichten", + "distributeHorizontally": "Horizontal verteilen", + "distributeVertically": "Vertikal verteilen", + "zoomToFit": "Einpassen zoom", + "zoomToSelection": "Auf Auswahl zoomen", + "locked": "Gesperrt", + "unlock": "Entsperren", + "lock": "Sperren", + "bringToFront": "Nach vorne bringen", + "sendToBack": "Nach hinten senden", + "group": "Gruppieren", + "ungroup": "Gruppierung aufheben" + }, + "mindmap": { + "addChild": "Unterthema hinzufügen", + "addSibling": "Geschwisterthema hinzufügen", + "addParent": "Übergeordnetes Thema hinzufügen", + "delete": "Löschen", + "insertAfter": "Danach einfügen", + "insertBefore": "Davor einfügen" + }, + "aiModel": { + "title": "KI-Modell", + "provider": "Anbieter", + "model": "Modell", + "temperature": "Temperatur", + "maxTokens": "Maximale Token", + "buttons": { + "retry": "Erneut versuchen", + "stop": "Stopp", + "clear": "Löschen" + }, + "thinking": "Denkt nach...", + "error": "KI-Fehler" } } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 4f83d73..f8d8f51 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -134,6 +134,7 @@ "openflowdsl": "Export as {{appName}} DSL", "figma": "Export to Figma", "share": "Share live canvas", + "shareEmbed": "Share & Embed", "exportDiagram": "Export Diagram", "exportAs": "Export As", "headingFormat": "Export Format", @@ -158,11 +159,12 @@ "hintCinematicVideo": "Dark launch-style build", "hintCinematicGif": "Dark social-ready loop", "hintShareViewer": "Invite link for this room", + "hintShareEmbed": "Read-only viewer link", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "Video", + "sectionCode": "Code", "chooseFormat": "Choose format", "speed": "Speed", "resolution": "Resolution", @@ -264,6 +266,7 @@ } }, "home": { + "appName": "OpenFlowKit", "title": "Dashboard", "description": "Manage your flows and diagrams.", "recentFiles": "Recent Files", @@ -281,6 +284,21 @@ "hint": "Names are local to this browser profile unless you export or sync them elsewhere.", "closeDialog": "Close rename flow dialog" }, + "continueTitle": "Continue with a recent action", + "homeEmptyTitle": "Create your first flow", + "homeEmptySubtitle": "Design enterprise-grade architectures instantly. Start from a blank canvas, describe your infrastructure with our AI builder, or use a tailored template.", + "homeBlankCanvas": "Blank Canvas", + "homeFlowpilotAI": "Flowpilot AI", + "homeTemplates": "Templates", + "homeImportFile": "Or import an existing file", + "suggestionBlank": "Blank canvas", + "suggestionBlankDesc": "Jump straight into the editor", + "suggestionAI": "Flowpilot AI", + "suggestionAIDesc": "Start from a prompt", + "suggestionImport": "Import", + "suggestionImportDesc": "Bring in existing work", + "suggestionTemplates": "Templates", + "suggestionTemplatesDesc": "Start from a proven pattern", "deleteFlow": { "title": "Delete flow", "description": "This removes the local autosaved flow from this device.", @@ -320,32 +338,28 @@ }, "properties": { "title": "Properties", - "nodeType": "Node Type", - "label": "Label", - "description": "Description", + "shape": "Shape", "color": "Color", "icon": "Icon", - "size": "Size", - "shape": "Shape", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", "bulkShape": "Bulk Shape", "bulkColor": "Bulk Color", "bulkIcon": "Bulk Icon", "labelTransform": "Label Transform", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", "findReplace": "Find & Replace", "findLabel": "Find", - "findPlaceholder": "Text to find", - "replaceLabel": "Replace with", - "replacePlaceholder": "Replacement text", - "useRegex": "Use Regular Expression", - "previewSummary": "Preview summary", - "bulkApplySummary": "Will update {{count}} selected nodes", - "selectFieldToApply": "Select at least one field to apply.", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", + "suffixOptional": "Suffix (optional)", + "useRegex": "Use Regex", "applyToSelectedNodes": "Apply to selected nodes", - "imageSettings": "Image Settings", - "transparency": "Transparency", - "rotation": "Rotation" + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "Selection summary" }, "saveStatus": { "saved": "Saved" @@ -376,7 +390,9 @@ "title": "History", "undo": "Undo", "redo": "Redo", - "clear": "Clear History" + "clear": "Clear History", + "undoUnavailable": "Nothing to undo yet.", + "redoUnavailable": "Nothing to redo right now." }, "errors": { "generic": "Something went wrong", @@ -408,6 +424,11 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", + "shortcutsTitle": "Start fast with shortcuts", + "shortcutsBadge": "Keyboard-first", + "shortcutCommandBar": "Open command center", + "shortcutHelp": "View keyboard shortcuts", + "shortcutCanvas": "Add a node on canvas", "getStarted": "Get Started" }, "footer": { @@ -758,6 +779,7 @@ "description": "Import code, infrastructure, SQL, or API specs into your diagram.", "uploadFile": "Upload file", "parse": "Parse", + "parseNativeProject": "Generate Native Diagram", "parsing": "Parsing...", "analyzing": "Analyzing...", "previewDsl": "Preview DSL", @@ -781,7 +803,8 @@ "sql": "Paste CREATE TABLE statements here...", "infra": "Paste Terraform state JSON, Kubernetes YAML, Docker Compose, or Terraform HCL here...", "openapi": "Paste your OpenAPI / Swagger YAML or JSON here...", - "code": "Paste your source code here..." + "code": "Paste your source code here...", + "mermaid": "Paste Mermaid diagram code here..." }, "infraFormats": { "terraformState": "Terraform State (.tfstate)", @@ -1312,7 +1335,11 @@ "annotationNode": { "placeholder": "*Double click to edit note*" }, + "contextMenu": { + "label": "Canvas context menu" + }, "connectMenu": { + "label": "Connect node menu", "createNewNode": "Create New Shape", "process": "Rounded Shape", "processDesc": "General-purpose block", @@ -1354,7 +1381,12 @@ "restoreVersion": "Restore version", "deleteVersion": "Delete version", "nodes": "{{count}} nodes", - "edges": "{{count}} edges" + "edges": "{{count}} edges", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "Flow Templates", @@ -1382,31 +1414,6 @@ "noSelection": "Nothing selected", "selectHint": "Click a node or edge to edit its properties" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "Selection summary" - }, "connectionPanel": { "architecture": "Architecture", "condition": "Condition", diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index 6e2fd36..df095cd 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -141,12 +141,14 @@ "gif": "GIF de reproducción", "hintPlaybackGif": "Bucle corto para docs/redes", "share": "Compartir lienzo en vivo", + "shareEmbed": "Compartir e incrustar", "hintShareViewer": "Enlace de invitación para esta sala", + "hintShareEmbed": "Enlace de visor de solo lectura", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "Video", + "sectionCode": "Code", "shareSection": "Compartir lienzo", "revealVideo": "Reveal Video", "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", @@ -240,6 +242,7 @@ } }, "home": { + "appName": "OpenFlowKit", "title": "Panel", "description": "Administre sus flujos y diagramas.", "recentFiles": "Archivos recientes", @@ -263,7 +266,22 @@ "confirmation": "¿Eliminar \"{{name}}\"?", "hint": "Esto no se puede deshacer a menos que tengas una copia exportada u otra copia.", "closeDialog": "Cerrar el diálogo de eliminar flujo" - } + }, + "suggestionBlank": "Lienzo en blanco", + "suggestionBlankDesc": "Saltar directamente al editor", + "suggestionAI": "Flowpilot IA", + "suggestionAIDesc": "Empezar desde un mensaje", + "suggestionImport": "Importar", + "suggestionImportDesc": "Traer trabajo existente", + "suggestionTemplates": "Plantillas", + "suggestionTemplatesDesc": "Empezar desde un patrón probado", + "continueTitle": "Continuar con una acción reciente", + "homeEmptyTitle": "Crea tu primer flujo", + "homeEmptySubtitle": "Diseña arquitecturas de nivel empresarial al instante. Comienza con un lienzo en blanco, describe tu infraestructura con nuestro constructor de IA, o usa una plantilla adaptada.", + "homeBlankCanvas": "Lienzo en blanco", + "homeFlowpilotAI": "Flowpilot IA", + "homeTemplates": "Plantillas", + "homeImportFile": "O importar un archivo existente" }, "settings": { "title": "Configuración", @@ -295,33 +313,29 @@ "help": "Ayuda" }, "properties": { - "title": "Propiedades", - "nodeType": "Tipo de nodo", - "label": "Etiqueta", - "description": "Descripción", + "title": "Properties", + "shape": "Shape", "color": "Color", - "icon": "Ícono", - "size": "Tamaño", - "shape": "Forma", - "bulkShape": "Forma múltiple", - "bulkColor": "Color múltiple", - "bulkIcon": "Ícono múltiple", - "labelTransform": "Transformación de etiqueta", - "prefixOptional": "Prefijo (opcional)", - "suffixOptional": "Sufijo (opcional)", - "findReplace": "Buscar y reemplazar", - "findLabel": "Buscar", - "findPlaceholder": "Texto a buscar", - "replaceLabel": "Reemplazar por", - "replacePlaceholder": "Texto de reemplazo", - "useRegex": "Usar expresión regular", - "previewSummary": "Resumen previo", - "bulkApplySummary": "Se actualizarán {{count}} elementos seleccionados", - "selectFieldToApply": "Seleccione al menos un campo para aplicar.", - "applyToSelectedNodes": "Aplicar a los elementos seleccionados", - "imageSettings": "Configuración de imagen", - "transparency": "Transparencia", - "rotation": "Rotación" + "icon": "Icon", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", + "bulkShape": "Bulk Shape", + "bulkColor": "Bulk Color", + "bulkIcon": "Bulk Icon", + "labelTransform": "Label Transform", + "findReplace": "Find & Replace", + "findLabel": "Find", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", + "suffixOptional": "Suffix (optional)", + "useRegex": "Use Regex", + "applyToSelectedNodes": "Apply to selected nodes", + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "Resumen de selección" }, "saveStatus": { "saved": "Guardado" @@ -346,7 +360,9 @@ "title": "Historial", "undo": "Deshacer", "redo": "Rehacer", - "clear": "Limpiar historial" + "clear": "Limpiar historial", + "undoUnavailable": "Nada que deshacer aún.", + "redoUnavailable": "Nada que rehacer ahora." }, "errors": { "generic": "Algo salió mal", @@ -378,7 +394,12 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", - "getStarted": "Get Started" + "getStarted": "Get Started", + "shortcutCommandBar": "Abrir centro de comandos", + "shortcutHelp": "Ver atajos de teclado", + "shortcutCanvas": "Agregar nodo en lienzo", + "shortcutsTitle": "Comienza rápido con atajos", + "shortcutsBadge": "Primero el teclado" }, "footer": { "mitLicensed": "Licencia MIT" @@ -653,7 +674,7 @@ "strokeWidth": "Ancho de trazo", "largeGraphSafety": "Protección para grafos grandes", "largeGraphSafetyAuto": "Auto", - "largeGraphSafetyOn": "Activado", + "largeGraphSafetyOn": "Seguridad de gráfico grande Activada", "largeGraphSafetyOff": "Desactivado", "exportModeDeterministic": "Determinista", "exportModeLegacy": "Heredado", @@ -712,11 +733,12 @@ "sql": "Pega aquí las sentencias CREATE TABLE...", "infra": "Pega aquí el JSON del estado de Terraform, YAML de Kubernetes, Docker Compose o Terraform HCL...", "openapi": "Pega aquí tu YAML o JSON de OpenAPI / Swagger...", - "code": "Pega aquí tu código fuente..." + "code": "Pega aquí tu código fuente...", + "mermaid": "Pega aquí el código del diagrama Mermaid..." }, "infraFormats": { - "terraformState": "Terraform State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "Estado de Terraform", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", "terraformHcl": "Terraform HCL (AI)" }, @@ -735,13 +757,16 @@ "infra": "Infra", "openapi": "OpenAPI", "code": "Code", - "codebase": "Repositorio" + "codebase": "Repositorio", + "mindmap": "Mapa mental", + "markdown": "Markdown" }, "title": "Importar desde datos", "description": "Importa código, infraestructura, SQL o especificaciones de API en tu diagrama.", "uploadFile": "Subir archivo", "parsing": "Analizando...", "parse": "Analizar", + "parseNativeProject": "Generate Native Diagram", "analyzing": "Procesando...", "aiActions": { "generateErd": "Generar DER (IA)", @@ -799,27 +824,25 @@ "flowpilotConfigurations": "Configuración de Flowpilot", "keyboardShortcuts": "Atajos de teclado", "canvas": { - "title": "Lienzo", - "showGrid": "Mostrar cuadrícula", - "showGridDesc": "Mostrar cuadrícula de puntos", - "snapToGrid": "Ajustar a cuadrícula", - "snapToGridDesc": "Alinear nodos al mover", - "miniMap": "Mini mapa", - "miniMapDesc": "Mostrar mini mapa abajo a la derecha", - "architectureStrictMode": "Modo estricto de arquitectura", - "architectureStrictModeDesc": "Bloquea la importación Mermaid cuando los diagnósticos de arquitectura incluyen problemas de recuperación/validación", - "alignmentGuides": "Guías de alineación", - "alignmentGuidesDesc": "Muestra guías inteligentes al arrastrar nodos", - "routingProfile": "Perfil de enrutamiento", + "title": "Canvas", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", + "routingProfile": "Routing Profile", "routingProfileStandard": "Estándar", "routingProfileInfrastructure": "Infraestructura", - "routingProfileHint": "El modo infraestructura favorece rutas ortogonales para mapas de servicios.", - "edgeBundling": "Agrupar aristas paralelas", - "edgeBundlingDesc": "Mantener conexiones paralelas en carriles compartidos" + "routingProfileHint": "El modo infraestructura sesga rutas ortogonales para mapas de servicios.", + "edgeBundling": "Agrupar bordes hermanos", + "edgeBundlingDesc": "Mantener conexiones paralelas en carriles compartidos", + "architectureStrictMode": "Modo Estricto de Arquitectura", + "architectureStrictModeDesc": "Bloquear importación de Mermaid cuando los diagnósticos de arquitectura incluyan problemas de recuperación/validación" }, "ai": { "provider": "Proveedor", - "model": "Modelo", + "model": "Modelo de IA", "apiKey": "Clave API", "customBaseUrl": "URL base personalizada", "optional": "Opcional", @@ -886,6 +909,135 @@ "browserFriendly": "Listo para navegador", "proxyLikely": "Probablemente requiere proxy", "mixed": "Depende del endpoint" + }, + "models": { + "gemini": { + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } + }, + "gemini-3-flash": { + "label": "Gemini 3 Flash" + }, + "gemini-3-pro": { + "label": "Gemini 3 Pro" + } + }, + "openai": { + "gpt-5-mini": { + "label": "GPT-5 Mini" + }, + "gpt-5": { + "2": { + "label": "GPT-5.2" + }, + "label": "GPT-5" + }, + "o4-mini": { + "label": "O4-Mini" + }, + "o3": { + "label": "O3" + } + }, + "claude": { + "claude-haiku-4-5": { + "label": "Claude Haiku 4.5" + }, + "claude-sonnet-4-5": { + "label": "Claude Sonnet 4.5" + }, + "claude-sonnet-4-6": { + "label": "Claude Sonnet 4.6" + }, + "claude-opus-4-6": { + "label": "Claude Opus 4.6" + } + }, + "groq": { + "meta-llama/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "meta-llama/llama-4-maverick-17b-128e-instruct": { + "label": "Llama 4 Maverick" + }, + "qwen/qwen3-32b": { + "label": "Qwen 3 32B" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } + } + }, + "nvidia": { + "meta/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "nvidia/nemotron-nano-12b-v2-vl": { + "label": "Nemotron Nano 12B" + }, + "deepseek/deepseek-v3-2": { + "label": "DeepSeek V3-2" + }, + "qwen/qwq-32b": { + "label": "QwQ 32B" + }, + "moonshotai/kimi-k2-thinking": { + "label": "Kimi K2 Thinking" + } + }, + "cerebras": { + "gpt-oss-120b": { + "label": "GPT OSS 120B" + }, + "qwen-3-32b": { + "label": "Qwen 3 32B" + }, + "qwen-3-235b-a22b": { + "label": "Qwen 3 235B" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } + } + }, + "mistral": { + "mistral-small-latest": { + "label": "Mistral Small" + }, + "mistral-medium-latest": { + "label": "Mistral Medium" + }, + "mistral-large-latest": { + "label": "Mistral Large" + }, + "codestral-latest": { + "label": "Codestral" + }, + "pixtral-large-latest": { + "label": "Pixtral Large" + } + } + }, + "customEndpoints": { + "ollama": { + "name": "Ollama" + }, + "lmStudio": { + "name": "LM Studio" + }, + "together": { + "name": "Together AI" + } } }, "brand": { @@ -926,7 +1078,19 @@ "analytics": { "enableTitle": "Analíticas de inicio anónimas", "enableDescription": "Compartir datos básicos de uso de forma anónima (opcional)" - } + }, + "search": "Buscar...", + "appearance": "Apariencia", + "account": "Cuenta", + "about": "Acerca de", + "language": "Idioma", + "theme": "Tema", + "fontSize": "Tamaño de fuente", + "fontFamily": "Familia de fuente", + "save": "Guardar", + "cancel": "Cancelar", + "reset": "Restablecer", + "confirm": "Confirmar" }, "customNodes": { "browserContent": "Contenido del navegador", @@ -995,7 +1159,8 @@ "note": "Nota adhesiva", "noteDesc": "Documentación", "releaseToConnect": "Soltar para conectar", - "close": "Cerrar menú de conexión" + "close": "Cerrar menú de conexión", + "label": "Menú de conexión de nodos" }, "errorBoundary": { "title": "Algo salió mal", @@ -1024,7 +1189,12 @@ "namedVersions": "Versiones con nombre", "noNamedSnapshots": "Aún no hay versiones con nombre.", "autosavedVersions": "Puntos de control autoguardados", - "noAutoSnapshots": "Aún no hay puntos de control autoguardados." + "noAutoSnapshots": "Aún no hay puntos de control autoguardados.", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "Plantillas de flujo", @@ -1052,31 +1222,6 @@ "noSelection": "Nada seleccionado", "selectHint": "Haz clic en un nodo o una arista para editar sus propiedades" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "Resumen de selección" - }, "flowCanvas": { "strictModePasteBlocked": "El modo estricto de arquitectura bloqueó el pegado de Mermaid. Abre la vista de código, corrige los diagnósticos y vuelve a intentarlo." }, @@ -1106,9 +1251,9 @@ }, "share": { "close": "Close", - "title": "Compartir diseño", + "title": "Compartir", "betaBadge": "Beta", - "description": "Invita a colaboradores a ver y editar este flujo contigo en tiempo real.", + "description": "Compartir este lienzo", "roomId": "ID de la sala", "link": "Enlace para compartir", "copied": "Copied Link!", @@ -1132,7 +1277,20 @@ "copyFailed": "No se pudo copiar el enlace para compartir.", "linkCopied": "Se copió el enlace de colaboración.", "copyManual": "El acceso al portapapeles está bloqueado. Copia el enlace manualmente desde el diálogo de compartir." - } + }, + "embed": "Insertar", + "embedCode": "Código de inserción", + "export": "Exportar", + "settings": "Configuración de compartir", + "anyoneWithLink": "Cualquiera con el enlace", + "viewOnly": "Solo lectura", + "canEdit": "Puede editar", + "disable": "Desactivar compartir", + "enable": "Activar compartir", + "invite": "Invitar", + "pending": "Pendiente", + "revoke": "Revocar", + "expired": "Expirado" }, "connectionPanel": { "architecture": "Arquitectura", @@ -1144,6 +1302,65 @@ "deleteConnection": "Eliminar conexión" }, "sidebar": { - "close": "Cerrar barra lateral" + "close": "Cerrar barra lateral", + "searchPlaceholder": "Buscar...", + "noResults": "Sin resultados", + "nodes": "Nodos", + "components": "Componentes", + "snippets": "Fragmentos", + "addons": "Complementos" + }, + "contextMenu": { + "label": "Menú contextual del lienzo" + }, + "canvas": { + "addNodeShortcut": "Agregar nodo", + "aiChatPlaceholder": "Crear algo...", + "nodes": "Nodos", + "connections": "Conexiones", + "elements": "Elementos", + "selection": "Selección", + "noSelection": "Sin selección", + "alignNodes": "Alinear nodos", + "distributeNodes": "Distribuir nodos", + "alignLeft": "Alinear a la izquierda", + "alignCenter": "Alinear al centro", + "alignRight": "Alinear a la derecha", + "alignTop": "Alinear arriba", + "alignMiddle": "Alinear al medio", + "alignBottom": "Alinear abajo", + "distributeHorizontally": "Distribuir horizontalmente", + "distributeVertically": "Distribuir verticalmente", + "zoomToFit": "Ajustar zoom", + "zoomToSelection": "Zoom a selección", + "locked": "Bloqueado", + "unlock": "Desbloquear", + "lock": "Bloquear", + "bringToFront": "Traer al frente", + "sendToBack": "Enviar atrás", + "group": "Agrupar", + "ungroup": "Desagrupar" + }, + "mindmap": { + "addChild": "Agregar subtema", + "addSibling": "Agregar tema hermano", + "addParent": "Agregar tema padre", + "delete": "Eliminar", + "insertAfter": "Insertar después", + "insertBefore": "Insertar antes" + }, + "aiModel": { + "title": "Modelo de IA", + "provider": "Proveedor", + "model": "Modelo", + "temperature": "Temperatura", + "maxTokens": "Máximo de tokens", + "buttons": { + "retry": "Reintentar", + "stop": "Detener", + "clear": "Limpiar" + }, + "thinking": "Pensando...", + "error": "Error de IA" } } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 9bc33a5..8f10646 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -87,7 +87,7 @@ "saveStatus": "État de sauvegarde locale", "autoSaved": "Enregistré localement à {{time}}.", "privacyShort": "Vos diagrammes restent sur cet appareil et n’atteignent pas nos serveurs.", - "beta": "BÊTA", + "beta": "BETA", "versionHistory": "Historique des versions", "loadJSON": "Charger JSON", "playbackMode": "Mode lecture", @@ -141,12 +141,14 @@ "gif": "GIF de lecture", "hintPlaybackGif": "Boucle courte pour docs/réseaux sociaux", "share": "Partager le canevas en direct", + "shareEmbed": "Partager et intégrer", "hintShareViewer": "Lien d’invitation pour cette salle", + "hintShareEmbed": "Lien de visualisation en lecture seule", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "Video", + "sectionCode": "Code", "shareSection": "Partager le canevas", "revealVideo": "Reveal Video", "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", @@ -240,6 +242,7 @@ } }, "home": { + "appName": "OpenFlowKit", "title": "Tableau de bord", "description": "Gérez vos flux et diagrammes.", "recentFiles": "Fichiers récents", @@ -263,7 +266,22 @@ "confirmation": "Supprimer \"{{name}}\" ?", "hint": "Cette action est irréversible sauf si vous avez un export de sauvegarde ou une autre copie.", "closeDialog": "Fermer la boîte de dialogue de suppression du flux" - } + }, + "suggestionBlank": "Canevas vierge", + "suggestionBlankDesc": "aller directement dans l'éditeur", + "suggestionAI": "Flowpilot IA", + "suggestionAIDesc": "Commencer à partir d'une invite", + "suggestionImport": "Importer", + "suggestionImportDesc": "Importer un travail existant", + "suggestionTemplates": "Modèles", + "suggestionTemplatesDesc": "Commencer à partir d'un modèle éprouvé", + "continueTitle": "Continuer avec une action récente", + "homeEmptyTitle": "Créez votre premier flux", + "homeEmptySubtitle": "Concevez des architectures de qualité entreprise instantanément. Commencez avec un canevas vierge, décrivez votre infrastructure avec notre constructeur IA, ou utilisez un modèle adapté.", + "homeBlankCanvas": "Canevas vierge", + "homeFlowpilotAI": "Flowpilot IA", + "homeTemplates": "Modèles", + "homeImportFile": "Ou importer un fichier existant" }, "settings": { "title": "Paramètres", @@ -295,33 +313,29 @@ "help": "Aide" }, "properties": { - "title": "Propriétés", - "nodeType": "Type de nœud", - "label": "Étiquette", - "description": "Description", - "color": "Couleur", - "icon": "Icône", - "size": "Taille", - "shape": "Forme", - "bulkShape": "Forme groupée", - "bulkColor": "Couleur groupée", - "bulkIcon": "Icône groupée", - "labelTransform": "Transformation d'étiquette", - "prefixOptional": "Préfixe (optionnel)", - "suffixOptional": "Suffixe (optionnel)", - "findReplace": "Rechercher et remplacer", - "findLabel": "Rechercher", - "findPlaceholder": "Texte à rechercher", - "replaceLabel": "Remplacer par", - "replacePlaceholder": "Texte de remplacement", - "useRegex": "Utiliser une expression régulière", - "previewSummary": "Aperçu", - "bulkApplySummary": "{{count}} éléments sélectionnés seront mis à jour", - "selectFieldToApply": "Sélectionnez au moins un champ à appliquer.", - "applyToSelectedNodes": "Appliquer aux éléments sélectionnés", - "imageSettings": "Paramètres de l'image", - "transparency": "Transparence", - "rotation": "Rotation" + "title": "Properties", + "shape": "Shape", + "color": "Color", + "icon": "Icon", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", + "bulkShape": "Bulk Shape", + "bulkColor": "Bulk Color", + "bulkIcon": "Bulk Icon", + "labelTransform": "Label Transform", + "findReplace": "Find & Replace", + "findLabel": "Find", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", + "suffixOptional": "Suffix (optional)", + "useRegex": "Use Regex", + "applyToSelectedNodes": "Apply to selected nodes", + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "Résumé de la sélection" }, "saveStatus": { "saved": "Enregistré" @@ -346,7 +360,9 @@ "title": "Historique", "undo": "Annuler", "redo": "Rétablir", - "clear": "Effacer l'historique" + "clear": "Effacer l'historique", + "undoUnavailable": "Rien à annuler pour le moment.", + "redoUnavailable": "Rien à refaire pour le moment." }, "errors": { "generic": "Quelque chose s'est mal passé", @@ -378,7 +394,12 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", - "getStarted": "Get Started" + "getStarted": "Get Started", + "shortcutCommandBar": "Ouvrir le centre de commandes", + "shortcutHelp": "Voir les raccourcis clavier", + "shortcutCanvas": "Ajouter un nœud sur le canevas", + "shortcutsTitle": "Démarrez rapidement avec les raccourcis", + "shortcutsBadge": "Clavier d'abord" }, "footer": { "mitLicensed": "Licence MIT" @@ -653,7 +674,7 @@ "strokeWidth": "Épaisseur du trait", "largeGraphSafety": "Protection grands graphes", "largeGraphSafetyAuto": "Auto", - "largeGraphSafetyOn": "Activé", + "largeGraphSafetyOn": "Sécurité grand graphique On", "largeGraphSafetyOff": "Désactivé", "exportModeDeterministic": "Déterministe", "exportModeLegacy": "Hérité", @@ -712,11 +733,12 @@ "sql": "Collez ici les instructions CREATE TABLE...", "infra": "Collez ici l'état Terraform en JSON, du YAML Kubernetes, Docker Compose ou Terraform HCL...", "openapi": "Collez ici votre YAML ou JSON OpenAPI / Swagger...", - "code": "Collez ici votre code source..." + "code": "Collez ici votre code source...", + "mermaid": "Collez ici le code du diagramme Mermaid..." }, "infraFormats": { - "terraformState": "Terraform State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "État Terraform", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", "terraformHcl": "Terraform HCL (AI)" }, @@ -735,13 +757,16 @@ "infra": "Infra", "openapi": "OpenAPI", "code": "Code", - "codebase": "Dépôt" + "codebase": "Dépôt", + "mindmap": "Carte mentale", + "markdown": "Markdown" }, "title": "Importer depuis des données", "description": "Importez du code, de l'infrastructure, du SQL ou des spécifications d'API dans votre diagramme.", "uploadFile": "Téléverser un fichier", "parsing": "Analyse en cours...", "parse": "Analyser", + "parseNativeProject": "Generate Native Diagram", "analyzing": "Analyse en cours...", "aiActions": { "generateErd": "Générer le MCD (IA)", @@ -799,27 +824,25 @@ "flowpilotConfigurations": "Configuration Flowpilot", "keyboardShortcuts": "Raccourcis clavier", "canvas": { - "title": "Canevas", - "showGrid": "Afficher la grille", - "showGridDesc": "Afficher une grille de points", - "snapToGrid": "Aligner sur la grille", - "snapToGridDesc": "Aligner les nœuds sur la grille", - "miniMap": "Mini carte", - "miniMapDesc": "Afficher la mini carte en bas à droite", - "architectureStrictMode": "Mode strict d’architecture", - "architectureStrictModeDesc": "Bloque l’import Mermaid lorsque les diagnostics d’architecture incluent des problèmes de récupération/validation", - "alignmentGuides": "Guides d’alignement", - "alignmentGuidesDesc": "Affiche des repères intelligents pendant le déplacement des nœuds", - "routingProfile": "Profil de routage", + "title": "Canvas", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", + "routingProfile": "Routing Profile", "routingProfileStandard": "Standard", "routingProfileInfrastructure": "Infrastructure", "routingProfileHint": "Le mode infrastructure privilégie les routes orthogonales pour les cartes de services.", - "edgeBundling": "Regrouper les arêtes parallèles", - "edgeBundlingDesc": "Conserver les connexions parallèles sur des voies partagées" + "edgeBundling": "Regrouper les bords siblings", + "edgeBundlingDesc": "Garder les connexions parallèles sur des voies partagées", + "architectureStrictMode": "Mode Strict Architecture", + "architectureStrictModeDesc": "Bloquer l'import Mermaid lorsque les diagnostics d'architecture incluent des problèmes de récupération/validation" }, "ai": { "provider": "Fournisseur", - "model": "Modèle", + "model": "Modèle IA", "apiKey": "Clé API", "customBaseUrl": "URL de base personnalisée", "optional": "Optionnel", @@ -886,6 +909,135 @@ "browserFriendly": "Compatible navigateur", "proxyLikely": "Proxy probable", "mixed": "Dépend du point de terminaison" + }, + "models": { + "gemini": { + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } + }, + "gemini-3-flash": { + "label": "Gemini 3 Flash" + }, + "gemini-3-pro": { + "label": "Gemini 3 Pro" + } + }, + "openai": { + "gpt-5-mini": { + "label": "GPT-5 Mini" + }, + "gpt-5": { + "2": { + "label": "GPT-5.2" + }, + "label": "GPT-5" + }, + "o4-mini": { + "label": "O4-Mini" + }, + "o3": { + "label": "O3" + } + }, + "claude": { + "claude-haiku-4-5": { + "label": "Claude Haiku 4.5" + }, + "claude-sonnet-4-5": { + "label": "Claude Sonnet 4.5" + }, + "claude-sonnet-4-6": { + "label": "Claude Sonnet 4.6" + }, + "claude-opus-4-6": { + "label": "Claude Opus 4.6" + } + }, + "groq": { + "meta-llama/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "meta-llama/llama-4-maverick-17b-128e-instruct": { + "label": "Llama 4 Maverick" + }, + "qwen/qwen3-32b": { + "label": "Qwen 3 32B" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } + } + }, + "nvidia": { + "meta/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "nvidia/nemotron-nano-12b-v2-vl": { + "label": "Nemotron Nano 12B" + }, + "deepseek/deepseek-v3-2": { + "label": "DeepSeek V3-2" + }, + "qwen/qwq-32b": { + "label": "QwQ 32B" + }, + "moonshotai/kimi-k2-thinking": { + "label": "Kimi K2 Thinking" + } + }, + "cerebras": { + "gpt-oss-120b": { + "label": "GPT OSS 120B" + }, + "qwen-3-32b": { + "label": "Qwen 3 32B" + }, + "qwen-3-235b-a22b": { + "label": "Qwen 3 235B" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } + } + }, + "mistral": { + "mistral-small-latest": { + "label": "Mistral Small" + }, + "mistral-medium-latest": { + "label": "Mistral Medium" + }, + "mistral-large-latest": { + "label": "Mistral Large" + }, + "codestral-latest": { + "label": "Codestral" + }, + "pixtral-large-latest": { + "label": "Pixtral Large" + } + } + }, + "customEndpoints": { + "ollama": { + "name": "Ollama" + }, + "lmStudio": { + "name": "LM Studio" + }, + "together": { + "name": "Together AI" + } } }, "brand": { @@ -926,7 +1078,19 @@ "analytics": { "enableTitle": "Analyses de lancement anonymes", "enableDescription": "Partager des données d’usage de base de manière anonyme (optionnel)" - } + }, + "search": "Rechercher...", + "appearance": "Apparence", + "account": "Compte", + "about": "À propos", + "language": "Langue", + "theme": "Thème", + "fontSize": "Taille de police", + "fontFamily": "Police", + "save": "Enregistrer", + "cancel": "Annuler", + "reset": "Réinitialiser", + "confirm": "Confirmer" }, "customNodes": { "browserContent": "Contenu du navigateur", @@ -995,7 +1159,8 @@ "note": "Note adhésive", "noteDesc": "Documentation", "releaseToConnect": "Relâcher pour connecter", - "close": "Fermer le menu de connexion" + "close": "Fermer le menu de connexion", + "label": "Menu de connexion des nœuds" }, "errorBoundary": { "title": "Quelque chose s'est mal passé", @@ -1024,7 +1189,12 @@ "namedVersions": "Versions nommées", "noNamedSnapshots": "Aucune version nommée pour le moment.", "autosavedVersions": "Points de contrôle sauvegardés automatiquement", - "noAutoSnapshots": "Aucun point de contrôle sauvegardé automatiquement pour le moment." + "noAutoSnapshots": "Aucun point de contrôle sauvegardé automatiquement pour le moment.", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "Modèles de flux", @@ -1052,31 +1222,6 @@ "noSelection": "Aucune sélection", "selectHint": "Cliquez sur un nœud ou une arête pour modifier ses propriétés" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "Résumé de la sélection" - }, "flowCanvas": { "strictModePasteBlocked": "Le mode strict d’architecture a bloqué le collage Mermaid. Ouvrez la vue Code, corrigez les diagnostics, puis réessayez." }, @@ -1106,9 +1251,9 @@ }, "share": { "close": "Close", - "title": "Partager le design", + "title": "Partager", "betaBadge": "Bêta", - "description": "Invitez des collaborateurs à consulter et modifier ce flux avec vous en temps réel.", + "description": "Partager ce canevas", "roomId": "ID de salle", "link": "Lien de partage", "copied": "Copied Link!", @@ -1132,7 +1277,20 @@ "copyFailed": "Impossible de copier le lien de partage.", "linkCopied": "Le lien de collaboration a été copié.", "copyManual": "L’accès au presse-papiers est bloqué. Copiez le lien manuellement depuis la boîte de dialogue de partage." - } + }, + "embed": "Intégrer", + "embedCode": "Code d'intégration", + "export": "Exporter", + "settings": "Paramètres de partage", + "anyoneWithLink": "Toute personne avec le lien", + "viewOnly": "Lecture seule", + "canEdit": "Peut modifier", + "disable": "Désactiver le partage", + "enable": "Activer le partage", + "invite": "Inviter", + "pending": "En attente", + "revoke": "Révoquer", + "expired": "Expiré" }, "connectionPanel": { "architecture": "Architecture", @@ -1144,6 +1302,65 @@ "deleteConnection": "Supprimer la connexion" }, "sidebar": { - "close": "Fermer la barre latérale" + "close": "Fermer la barre latérale", + "searchPlaceholder": "Rechercher...", + "noResults": "Aucun résultat", + "nodes": "Nœuds", + "components": "Composants", + "snippets": "Extraits", + "addons": "Add-ons" + }, + "contextMenu": { + "label": "Menu contextuel du canevas" + }, + "canvas": { + "addNodeShortcut": "Ajouter un nœud", + "aiChatPlaceholder": "Créer quelque chose...", + "nodes": "Nœuds", + "connections": "Connexions", + "elements": "Éléments", + "selection": "Sélection", + "noSelection": "Aucune sélection", + "alignNodes": "Aligner les nœuds", + "distributeNodes": "Distribuer les nœuds", + "alignLeft": "Aligner à gauche", + "alignCenter": "Aligner au centre", + "alignRight": "Aligner à droite", + "alignTop": "Aligner en haut", + "alignMiddle": "Aligner au milieu", + "alignBottom": "Aligner en bas", + "distributeHorizontally": "Distribuer horizontalement", + "distributeVertically": "Distribuer verticalement", + "zoomToFit": "Zoom pour ajuster", + "zoomToSelection": "Zoom sur la sélection", + "locked": "Verrouillé", + "unlock": "Déverrouiller", + "lock": "Verrouiller", + "bringToFront": "Mettre au premier plan", + "sendToBack": "Envoyer à l'arrière", + "group": "Grouper", + "ungroup": "Dissocier" + }, + "mindmap": { + "addChild": "Ajouter un sous-sujet", + "addSibling": "Ajouter un sujet frère", + "addParent": "Ajouter un sujet parent", + "delete": "Supprimer", + "insertAfter": "Insérer après", + "insertBefore": "Insérer avant" + }, + "aiModel": { + "title": "Modèle IA", + "provider": "Fournisseur", + "model": "Modèle", + "temperature": "Température", + "maxTokens": "Jetons max", + "buttons": { + "retry": "Réessayer", + "stop": "Arrêter", + "clear": "Effacer" + }, + "thinking": "Réflexion...", + "error": "Erreur IA" } } diff --git a/public/locales/ja/translation.json b/public/locales/ja/translation.json index 2f1f1f1..c798612 100644 --- a/public/locales/ja/translation.json +++ b/public/locales/ja/translation.json @@ -141,12 +141,14 @@ "gif": "再生GIF", "hintPlaybackGif": "ドキュメントやSNS向けの短いループ", "share": "ライブキャンバスを共有", + "shareEmbed": "共有と埋め込み", "hintShareViewer": "このルームへの招待リンク", + "hintShareEmbed": "読み取り専用ビューアーリンク", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "Video", + "sectionCode": "Code", "shareSection": "キャンバスを共有", "revealVideo": "Reveal Video", "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", @@ -240,6 +242,7 @@ } }, "home": { + "appName": "オープンフローキット", "title": "ダッシュボード", "description": "フローと図を管理します。", "recentFiles": "最近のファイル", @@ -263,7 +266,22 @@ "confirmation": "「{{name}}」を削除しますか?", "hint": "エクスポートしたバックアップまたは別のコピーがない限り、この操作は元に戻せません。", "closeDialog": "フロー削除ダイアログを閉じる" - } + }, + "suggestionBlank": "空白のキャンバス", + "suggestionBlankDesc": "エディタに直接ジャンプ", + "suggestionAI": "フローパイロット人工知能", + "suggestionAIDesc": "プロンプトから始める", + "suggestionImport": "インポート", + "suggestionImportDesc": "既存の作品を持ち込む", + "suggestionTemplates": "テンプレート", + "suggestionTemplatesDesc": "実証済みのパターンから始める", + "continueTitle": "最近の操作を続ける", + "homeEmptyTitle": "最初のフローを作成", + "homeEmptySubtitle": "エンタープライズグレードのアーキテクチャを即座に設計。空白のキャンバスから始めるか、AIビルダーでインフラを描述するか、カスタマイズテンプレートを使用してください。", + "homeBlankCanvas": "空白のキャンバス", + "homeFlowpilotAI": "フローパイロット人工知能", + "homeTemplates": "テンプレート", + "homeImportFile": "または既存のファイルをインポート" }, "settings": { "title": "設定", @@ -295,33 +313,29 @@ "help": "ヘルプ" }, "properties": { - "title": "プロパティ", - "nodeType": "ノードタイプ", - "label": "ラベル", - "description": "説明", - "color": "色", - "icon": "アイコン", - "size": "サイズ", - "shape": "図形", - "bulkShape": "複数図形", - "bulkColor": "一括カラー", - "bulkIcon": "一括アイコン", - "labelTransform": "ラベル変換", - "prefixOptional": "接頭辞(任意)", - "suffixOptional": "接尾辞(任意)", - "findReplace": "検索と置換", - "findLabel": "検索", - "findPlaceholder": "検索するテキスト", - "replaceLabel": "置換後の文字列", - "replacePlaceholder": "置換テキスト", - "useRegex": "正規表現を使用", - "previewSummary": "プレビュー", - "bulkApplySummary": "選択中の {{count}} 項目を更新します", - "selectFieldToApply": "適用する項目を少なくとも 1 つ選択してください。", - "applyToSelectedNodes": "選択した項目に適用", - "imageSettings": "画像設定", - "transparency": "透明度", - "rotation": "回転" + "title": "Properties", + "shape": "Shape", + "color": "Color", + "icon": "Icon", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", + "bulkShape": "Bulk Shape", + "bulkColor": "Bulk Color", + "bulkIcon": "Bulk Icon", + "labelTransform": "Label Transform", + "findReplace": "Find & Replace", + "findLabel": "Find", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", + "suffixOptional": "Suffix (optional)", + "useRegex": "Use Regex", + "applyToSelectedNodes": "Apply to selected nodes", + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "選択の概要" }, "saveStatus": { "saved": "保存済み" @@ -346,7 +360,9 @@ "title": "履歴", "undo": "元に戻す", "redo": "やり直す", - "clear": "履歴をクリア" + "clear": "履歴をクリア", + "undoUnavailable": "まだ元に戻すものがありません。", + "redoUnavailable": "やり直すものがありません。" }, "errors": { "generic": "問題が発生しました", @@ -378,7 +394,12 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", - "getStarted": "Get Started" + "getStarted": "Get Started", + "shortcutCommandBar": "コマンドセンターを開く", + "shortcutHelp": "キーボードショートカットを表示", + "shortcutCanvas": "キャンバスにノードを追加", + "shortcutsTitle": "ショートカットで素早く開始", + "shortcutsBadge": "キーボードファースト" }, "footer": { "mitLicensed": "MITライセンス" @@ -437,7 +458,7 @@ "description": "究極のホワイトラベルキャンバス。", "diagramAsCode": "コードとしての図", "diagramAsCodeDesc": "Mermaid.jsとDSLをサポート。", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot 人工知能", "aiAssistant": "AIアシスタント", "flowpilotAIDesc": "ガイド付きAI編集で図を調整します。", "addRedisCache": "DBの前にRedisキャッシュを追加する。", @@ -495,7 +516,7 @@ "communityDesc": "OpenFlowKitを活用している開発者に参加しましょう。", "roadmap": "ロードマップ", "coreRenderer": "コアレンダラー", - "flowpilotAI": "Flowpilot" + "flowpilotAI": "Flowpilot 人工知能" }, "demo": { "livePreview": "ライブプレビュー", @@ -636,7 +657,7 @@ "visuals": { "title": "接続スタイル", "edgeStyle": "エッジスタイル", - "bezier": "ベジェ", + "bezier": "ベジェ曲線", "bezierDesc": "滑らかな曲線", "straight": "直線", "straightDesc": "直接接続", @@ -653,7 +674,7 @@ "strokeWidth": "線の太さ", "largeGraphSafety": "大規模グラフ保護", "largeGraphSafetyAuto": "自動", - "largeGraphSafetyOn": "オン", + "largeGraphSafetyOn": "大規模グラフ安全モードオン", "largeGraphSafetyOff": "オフ", "exportModeDeterministic": "決定的", "exportModeLegacy": "従来方式", @@ -712,11 +733,12 @@ "sql": "ここに CREATE TABLE 文を貼り付けてください...", "infra": "ここに Terraform state JSON、Kubernetes YAML、Docker Compose、または Terraform HCL を貼り付けてください...", "openapi": "ここに OpenAPI / Swagger の YAML または JSON を貼り付けてください...", - "code": "ここにソースコードを貼り付けてください..." + "code": "ここにソースコードを貼り付けてください...", + "mermaid": "ここに Mermaid 図のコードを貼り付けてください..." }, "infraFormats": { - "terraformState": "Terraform State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "Terraform状態", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", "terraformHcl": "Terraform HCL (AI)" }, @@ -735,13 +757,16 @@ "infra": "Infra", "openapi": "OpenAPI", "code": "Code", - "codebase": "リポジトリ" + "codebase": "リポジトリ", + "mindmap": "マインドマップ", + "markdown": "Markdown" }, "title": "データからインポート", "description": "コード、インフラ、SQL、または API 仕様を図に取り込みます。", "uploadFile": "ファイルをアップロード", "parsing": "解析中...", "parse": "解析", + "parseNativeProject": "Generate Native Diagram", "analyzing": "分析中...", "aiActions": { "generateErd": "ERD を生成 (AI)", @@ -792,34 +817,32 @@ "settingsModal": { "title": "設定", "general": "一般", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot 人工知能", "shortcuts": "ショートカット", "running": "{appName} 実行中", "generalSettings": "一般設定", "flowpilotConfigurations": "Flowpilot設定", "keyboardShortcuts": "キーボードショートカット", "canvas": { - "title": "キャンバス", - "showGrid": "グリッドを表示", - "showGridDesc": "ドットグリッドを表示", - "snapToGrid": "グリッドにスナップ", - "snapToGridDesc": "ノードを自動でスナップ", - "miniMap": "ミニマップ", - "miniMapDesc": "右下にミニマップを表示", - "architectureStrictMode": "アーキテクチャ厳格モード", - "architectureStrictModeDesc": "アーキテクチャ診断に回復/検証の問題が含まれる場合、Mermaid のインポートをブロックします", - "alignmentGuides": "整列ガイド", - "alignmentGuidesDesc": "ノードをドラッグ中にスマートガイド線を表示します", - "routingProfile": "ルーティングプロファイル", + "title": "Canvas", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", + "routingProfile": "Routing Profile", "routingProfileStandard": "標準", "routingProfileInfrastructure": "インフラストラクチャ", - "routingProfileHint": "インフラストラクチャモードでは、サービスマップ向けに直交ルートを優先します。", - "edgeBundling": "平行エッジを束ねる", - "edgeBundlingDesc": "平行接続を共通レーン上に維持する" + "routingProfileHint": "インフラストラクチャモードはサービスマップのために直交ルートを優先します。", + "edgeBundling": "兄弟エッジをバンドル", + "edgeBundlingDesc": "並行接続を共有レーンに保つ", + "architectureStrictMode": "アーキテクチャStrictモード", + "architectureStrictModeDesc": "アーキテクチャ診断が回復/検証の問題を含む場合、Mermaidインポートをブロック" }, "ai": { "provider": "プロバイダー", - "model": "モデル", + "model": "AIモデル", "apiKey": "APIキー", "customBaseUrl": "カスタムURL", "optional": "任意", @@ -886,6 +909,135 @@ "browserFriendly": "ブラウザ向け", "proxyLikely": "プロキシが必要な可能性", "mixed": "エンドポイント次第" + }, + "models": { + "gemini": { + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } + }, + "gemini-3-flash": { + "label": "Gemini 3 Flash" + }, + "gemini-3-pro": { + "label": "Gemini 3 Pro" + } + }, + "openai": { + "gpt-5-mini": { + "label": "GPT-5 Mini" + }, + "gpt-5": { + "2": { + "label": "GPT-5.2" + }, + "label": "GPT-5" + }, + "o4-mini": { + "label": "O4-Mini" + }, + "o3": { + "label": "O3" + } + }, + "claude": { + "claude-haiku-4-5": { + "label": "Claude Haiku 4.5" + }, + "claude-sonnet-4-5": { + "label": "Claude Sonnet 4.5" + }, + "claude-sonnet-4-6": { + "label": "Claude Sonnet 4.6" + }, + "claude-opus-4-6": { + "label": "Claude Opus 4.6" + } + }, + "groq": { + "meta-llama/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "meta-llama/llama-4-maverick-17b-128e-instruct": { + "label": "Llama 4 Maverick" + }, + "qwen/qwen3-32b": { + "label": "Qwen 3 32B" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } + } + }, + "nvidia": { + "meta/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "nvidia/nemotron-nano-12b-v2-vl": { + "label": "Nemotron Nano 12B" + }, + "deepseek/deepseek-v3-2": { + "label": "DeepSeek V3-2" + }, + "qwen/qwq-32b": { + "label": "QwQ 32B" + }, + "moonshotai/kimi-k2-thinking": { + "label": "Kimi K2 Thinking" + } + }, + "cerebras": { + "gpt-oss-120b": { + "label": "GPT OSS 120B" + }, + "qwen-3-32b": { + "label": "Qwen 3 32B" + }, + "qwen-3-235b-a22b": { + "label": "Qwen 3 235B" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } + } + }, + "mistral": { + "mistral-small-latest": { + "label": "Mistral Small" + }, + "mistral-medium-latest": { + "label": "Mistral Medium" + }, + "mistral-large-latest": { + "label": "Mistral Large" + }, + "codestral-latest": { + "label": "Codestral" + }, + "pixtral-large-latest": { + "label": "Pixtral Large" + } + } + }, + "customEndpoints": { + "ollama": { + "name": "Ollama" + }, + "lmStudio": { + "name": "LM Studio" + }, + "together": { + "name": "Together AI" + } } }, "brand": { @@ -926,7 +1078,19 @@ "analytics": { "enableTitle": "匿名の起動分析", "enableDescription": "匿名の基本的な利用データを共有します(任意)" - } + }, + "search": "検索...", + "appearance": "外観", + "account": "アカウント", + "about": "概要", + "language": "言語", + "theme": "テーマ", + "fontSize": "フォントサイズ", + "fontFamily": "フォント", + "save": "保存", + "cancel": "キャンセル", + "reset": "リセット", + "confirm": "確認" }, "customNodes": { "browserContent": "ブラウザコンテンツ", @@ -995,7 +1159,8 @@ "note": "付箋", "noteDesc": "ドキュメント", "releaseToConnect": "接続するには離す", - "close": "接続メニューを閉じる" + "close": "接続メニューを閉じる", + "label": "ノード接続メニュー" }, "errorBoundary": { "title": "問題が発生しました", @@ -1024,7 +1189,12 @@ "namedVersions": "名前付きバージョン", "noNamedSnapshots": "まだ名前付きバージョンはありません。", "autosavedVersions": "自動保存チェックポイント", - "noAutoSnapshots": "まだ自動保存チェックポイントはありません。" + "noAutoSnapshots": "まだ自動保存チェックポイントはありません。", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "フローテンプレート", @@ -1052,31 +1222,6 @@ "noSelection": "何も選択されていません", "selectHint": "ノードまたはエッジをクリックしてプロパティを編集してください" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "選択の概要" - }, "flowCanvas": { "strictModePasteBlocked": "アーキテクチャ厳格モードにより Mermaid の貼り付けがブロックされました。コードビューを開き、診断を修正してから再試行してください。" }, @@ -1106,9 +1251,9 @@ }, "share": { "close": "閉じる", - "title": "デザインを共有", + "title": "共有", "betaBadge": "ベータ", - "description": "共同編集者を招待して、このフローをリアルタイムで閲覧・編集してもらえます。", + "description": "このキャンバスを共有", "roomId": "ルームID", "link": "共有リンク", "copied": "リンクをコピーしました!", @@ -1132,7 +1277,20 @@ "copyFailed": "共有リンクをコピーできませんでした。", "linkCopied": "共同編集リンクをコピーしました。", "copyManual": "クリップボードへのアクセスがブロックされています。共有ダイアログからリンクを手動でコピーしてください。" - } + }, + "embed": "埋め込み", + "embedCode": "埋め込みコード", + "export": "エクスポート", + "settings": "共有設定", + "anyoneWithLink": "リンクを持つ任何人", + "viewOnly": "表示のみ", + "canEdit": "編集可能", + "disable": "共有を無効化", + "enable": "共有を有効化", + "invite": "招待", + "pending": "保留中", + "revoke": "取り消し", + "expired": "期限切れ" }, "connectionPanel": { "architecture": "アーキテクチャ", @@ -1144,6 +1302,65 @@ "deleteConnection": "接続を削除" }, "sidebar": { - "close": "サイドバーを閉じる" + "close": "サイドバーを閉じる", + "searchPlaceholder": "検索...", + "noResults": "結果なし", + "nodes": "ノード", + "components": "コンポーネント", + "snippets": "スニペット", + "addons": "アドオン" + }, + "contextMenu": { + "label": "キャンバスコンテキストメニュー" + }, + "canvas": { + "addNodeShortcut": "ノードを追加", + "aiChatPlaceholder": "何かを作成...", + "nodes": "ノード", + "connections": "接続", + "elements": "要素", + "selection": "選択", + "noSelection": "選択なし", + "alignNodes": "ノードを整列", + "distributeNodes": "ノードを分布", + "alignLeft": "左揃え", + "alignCenter": "中央揃え", + "alignRight": "右揃え", + "alignTop": "上揃え", + "alignMiddle": "中間揃え", + "alignBottom": "下揃え", + "distributeHorizontally": "水平に分布", + "distributeVertically": "垂直に分布", + "zoomToFit": "フィットにズーム", + "zoomToSelection": "選択にズーム", + "locked": "ロック済み", + "unlock": "ロック解除", + "lock": "ロック", + "bringToFront": "最前面へ", + "sendToBack": "最背面へ", + "group": "グループ化", + "ungroup": "グループ解除" + }, + "mindmap": { + "addChild": "サブトピックを追加", + "addSibling": "兄弟トピックを追加", + "addParent": "親トピックを追加", + "delete": "削除", + "insertAfter": "後に挿入", + "insertBefore": "前に挿入" + }, + "aiModel": { + "title": "AIモデル", + "provider": "プロバイダー", + "model": "モデル", + "temperature": "温度", + "maxTokens": "最大トークン数", + "buttons": { + "retry": "再試行", + "stop": "停止", + "clear": "クリア" + }, + "thinking": "思考中...", + "error": "AIエラー" } } diff --git a/public/locales/tr/translation.json b/public/locales/tr/translation.json index 239ec7e..e63099a 100644 --- a/public/locales/tr/translation.json +++ b/public/locales/tr/translation.json @@ -11,7 +11,6 @@ "close": "Kapat", "back": "Geri", "next": "Sonraki", - "previous": "Önceki", "done": "Tamam", "undo": "Geri Al", "redo": "Yinele", @@ -47,13 +46,10 @@ "loading": "Yükleniyor...", "error": "Hata", "success": "Başarılı", - "settings": "Ayarlar", "help": "Yardım", "selectTool": "Seçim Aracı", "handTool": "El Aracı", - "docs": "Dokümantasyon", "getStarted": "Hemen Başla", - "publicBeta": "v1.0 Public Beta", "bringToFront": "Öne Getir", "sendToBack": "Arkaya Gönder", "reverseDirection": "Yönü Tersine Çevir", @@ -74,7 +70,7 @@ "export": "Dışa Aktar", "exportDiagram": "Diyagramı Dışa Aktar", "exportAs": "Farklı Dışa Aktar", - "rename": "Rename" + "rename": "Yeniden Adlandır" }, "nav": { "home": "Ana Sayfa", @@ -98,7 +94,7 @@ "versionHistory": "Sürüm Geçmişi", "loadJSON": "JSON Yükle", "playbackMode": "Oynatma Modu", - "privacyMessage": "Your diagrams stay with you and do not reach our servers.", + "privacyMessage": "Diyagramlarınız sizinle kalır ve sunucularımıza ulaşmaz.", "templates": "Şablonlar" }, "menu": { @@ -140,30 +136,32 @@ "hintWhiteBg4K": "Beyaz Arka Plan (4K)", "hintDownload": "İndir", "hintClipboard": "Kopyala", - "exportOrShare": "Export or share this canvas", - "svg": "Export as SVG", - "hintSvgScalable": "Scalable vector file", - "video": "Playback Video", - "hintPlaybackWebM": "Playback timeline (WebM/MP4)", - "gif": "Playback GIF", - "hintPlaybackGif": "Short loop for docs/social", - "share": "Share live canvas", - "hintShareViewer": "Invite link for this room", - "readmeEmbed": "README Embed", - "hintReadmeEmbed": "Copy Markdown snippet", - "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", - "shareSection": "Share canvas", - "revealVideo": "Reveal Video", - "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", - "revealGif": "Reveal GIF", - "hintRevealGif": "Animated reveal for docs/social", - "cinematicVideo": "Cinematic Build Video", - "hintCinematicVideo": "Dark launch-style build", - "cinematicGif": "Cinematic Build GIF", - "hintCinematicGif": "Dark social-ready loop", - "actionDownload": "Download", + "exportOrShare": "Bu tuvali dışa aktar veya paylaş", + "svg": "SVG Olarak Dışa Aktar", + "hintSvgScalable": "Ölçeklenebilir vektör dosyası", + "video": "Oynatma Videosu", + "hintPlaybackWebM": "Oynatma zaman çizelgesi (WebM/MP4)", + "gif": "Oynatma GIF", + "hintPlaybackGif": "Belgeler/sosyal medya için kısa döngü", + "share": "Canlı tuvali paylaş", + "shareEmbed": "Paylaş ve Göm", + "hintShareViewer": "Bu oda için davet bağlantısı", + "hintShareEmbed": "Salt okunur görüntüleyici bağlantısı", + "readmeEmbed": "README Yerleşimi", + "hintReadmeEmbed": "Markdown snippet kopyala", + "sectionImage": "Görsel", + "sectionVideo": "Video", + "sectionCode": "Kod", + "shareSection": "Tuvali paylaş", + "revealVideo": "Videoyu Göster", + "hintRevealVideo": "Düğümler sırayla belirir (WebM/MP4)", + "revealGif": "GIF Göster", + "hintRevealGif": "Belgeler/sosyal medya için animasyonlu gösterim", + "cinematicVideo": "Sinematik Yapım Videosu", + "hintCinematicVideo": "Karanlık lansman tarzı yapım", + "cinematicGif": "Sinematik Yapım GIF", + "hintCinematicGif": "Karanlık sosyal medya döngüsü", + "actionDownload": "İndir", "hintDocument": "Belge", "hintEditableSvg": "Düzenlenebilir SVG", "chooseFormat": "Biçim seç", @@ -194,13 +192,13 @@ "newSection": "Yeni Bölüm", "section": "Bölüm", "text": "Metin", - "image": "Resim", + "image": "Görsel", "group": "Grup", "items": "öğe", "database": "Veritabanı", "inputOutput": "Giriş / Çıkış", "branch": "Dal", - "mindmap": "Topic" + "mindmap": "Konu" }, "actions": { "clearCanvasConfirm": "Tuvali temizlemek istediğinizden emin misiniz?" @@ -218,7 +216,7 @@ "subtitle": "Geliştiriciler İçin Yapıldı", "description": "Kod veya tuval ile çarpıcı akış şemaları oluşturun. İstediğiniz formata aktarın. Açık kaynak ve sonsuza kadar ücretsiz.", "livePreview": "Canlı Önizleme", - "publicBeta": "v1.0 Public Beta", + "publicBeta": "v1.0 Genel Beta", "description1": "Diyagram motoru", "description2": "Sizin gibi", "description3": "", @@ -267,30 +265,46 @@ } }, "home": { + "appName": "OpenFlowKit", "title": "Gösterge Paneli", "description": "Akışlarınızı ve diyagramlarınızı yönetin.", "recentFiles": "Son Dosyalar", "files": "dosyalar", "createFirstFlow": "İlk akışınızı oluşturun", "startFromScratch": "Sıfırdan başlayın veya mevcut bir diyagramı içe aktarın.", - "currentFlow": "Current flow", - "autosaved": "Autosaved", - "localStorageHint": "Autosaved on this device. We do not upload your diagram data to our servers.", + "currentFlow": "Mevcut akış", + "autosaved": "Otomatik kaydedildi", + "localStorageHint": "Bu cihazda otomatik kaydedildi. Diyagram verilerinizi sunucularımıza yüklemiyoruz.", "renameFlow": { - "title": "Rename flow", - "description": "Update the name shown on your dashboard and in the editor.", - "label": "Flow name", - "placeholder": "Enter a flow name", - "hint": "Names are local to this browser profile unless you export or sync them elsewhere.", - "closeDialog": "Close rename flow dialog" + "title": "Akışı yeniden adlandır", + "description": "Gösterge panelinizde ve editörde görünen adı güncelleyin.", + "label": "Akış adı", + "placeholder": "Bir akış adı girin", + "hint": "Adlar, dışa aktarmadığınız veya başka bir yerde senkronize etmediğiniz sürece bu tarayıcı profilinde yereldir.", + "closeDialog": "Akış yeniden adlandırma iletişim kutusunu kapat" }, "deleteFlow": { - "title": "Delete flow", - "description": "This removes the local autosaved flow from this device.", - "confirmation": "Delete \"{{name}}\"?", - "hint": "This cannot be undone unless you have an exported backup or another copy.", - "closeDialog": "Close delete flow dialog" - } + "title": "Akışı sil", + "description": "Bu, yerel otomatik kaydedilen akışı bu cihazdan kaldırır.", + "confirmation": "\"{{name}}\" silinsin mi?", + "hint": "Dışa aktarılmış bir yedeklemeniz veya başka bir kopyanız yoksa bu işlem geri alınamaz.", + "closeDialog": "Akış silme iletişim kutusunu kapat" + }, + "suggestionBlank": "Boş tuval", + "suggestionBlankDesc": "Doğrudan editöre geç", + "suggestionAI": "Flowpilot Yapay Zeka", + "suggestionAIDesc": "Bir prompt ile başla", + "suggestionImport": "İçe Aktar", + "suggestionImportDesc": "Mevcut çalışmanı getir", + "suggestionTemplates": "Şablonlar", + "suggestionTemplatesDesc": "Kanıtlanmış bir kalıptan başla", + "continueTitle": "Son eylemle devam et", + "homeEmptyTitle": "İlk akışınızı oluşturun", + "homeEmptySubtitle": "Kurumsal düzey mimariileri anında tasarlayın. Boş bir tuvalden başlayın, altyapınızı AI builderımızla tanımlayın veya hazır bir şablon kullanın.", + "homeBlankCanvas": "Boş Tuval", + "homeFlowpilotAI": "Flowpilot Yapay Zeka", + "homeTemplates": "Şablonlar", + "homeImportFile": "Veya mevcut bir dosyayı içe aktarın" }, "settings": { "title": "Ayarlar", @@ -307,9 +321,9 @@ "about": "Hakkında", "brand": "Marka Ayarları", "privacy": "Gizlilik", - "themeLight": "Light", - "themeDark": "Dark", - "themeSystem": "System" + "themeLight": "Açık", + "themeDark": "Koyu", + "themeSystem": "Sistem" }, "shortcuts": { "title": "Klavye Kısayolları", @@ -323,32 +337,28 @@ }, "properties": { "title": "Özellikler", - "nodeType": "Düğüm Türü", - "label": "Etiket", - "description": "Açıklama", + "shape": "Şekil", "color": "Renk", "icon": "İkon", - "size": "Boyut", - "shape": "Şekil", + "rotation": "Döndürme", + "transparency": "Saydamlık", + "imageSettings": "Görsel Ayarları", "bulkShape": "Toplu Şekil", "bulkColor": "Toplu Renk", "bulkIcon": "Toplu İkon", "labelTransform": "Etiket Dönüşümü", - "prefixOptional": "Önek (isteğe bağlı)", - "suffixOptional": "Sonek (isteğe bağlı)", "findReplace": "Bul ve Değiştir", "findLabel": "Bul", "findPlaceholder": "Bulunacak metin", - "replaceLabel": "Şununla değiştir", - "replacePlaceholder": "Yeni metin", + "replaceLabel": "Değiştir", + "replacePlaceholder": "Değiştirilecek metin", + "prefixOptional": "Önek (isteğe bağlı)", + "suffixOptional": "Sonek (isteğe bağlı)", "useRegex": "Düzenli ifade kullan", - "previewSummary": "Önizleme özeti", - "bulkApplySummary": "Seçili {{count}} öğe güncellenecek", - "selectFieldToApply": "Uygulamak için en az bir alan seçin.", "applyToSelectedNodes": "Seçili öğelere uygula", - "imageSettings": "Görsel Ayarları", - "transparency": "Saydamlık", - "rotation": "Döndürme" + "selectFieldToApply": "Uygulamak için bir alan seçin", + "previewSummary": "Önizleme özeti", + "selectionSummary": "Seçim özeti" }, "saveStatus": { "saved": "Kaydedildi" @@ -356,7 +366,7 @@ "ai": { "generate": "Yapay Zeka ile Oluştur", "provider": "Yapay Zeka Sağlayıcı", - "model": "Model", + "model": "Yapay Zeka Modeli", "apiKey": "API Anahtarı", "placeholder": "Akış şemanızı açıklayın...", "settingsSubtitle": "Tercih ettiğiniz yapay zeka sağlayıcısını, modeli ve API anahtarını aşağıdan yapılandırın.", @@ -366,7 +376,7 @@ "customEndpointTitle": "Özel endpoint nedir?", "customModelHint": "Endpoint'iniz için tam model kimliğini girin", "privacyTitle": "Gizlilik ve Şifreleme", - "generateWithFlowpilot": "Generate with Flowpilot" + "generateWithFlowpilot": "Flowpilot ile oluştur" }, "playback": { "title": "Oynatma", @@ -379,7 +389,9 @@ "title": "Geçmiş", "undo": "Geri Al", "redo": "Yinele", - "clear": "Geçmişi Temizle" + "clear": "Geçmişi Temizle", + "undoUnavailable": "Geri alınacak bir şey yok.", + "redoUnavailable": "İleri alınacak bir şey yok." }, "errors": { "generic": "Bir şeyler ters gitti", @@ -391,7 +403,7 @@ "welcome": { "title": "OpenFlowKit", "description": "Geliştirici odaklı tuval üzerinde güzel, yapılandırılmış diyagramlar tasarlayın.", - "getStarted": "Get Started", + "getStarted": "Hemen Başla", "press": "Kısayollar için", "shortcuts": "tuşlara basın", "privacy": "Diyagramlarınız, API anahtarlarınız ve tüm verileriniz yalnızca cihazınızda saklanır.", @@ -402,16 +414,21 @@ "privateSecure": "Özel ve Güvenli", "localFirst": "Yerel öncelikli mimari verilerinizi her zaman güvende tutar." }, - "feature1Title": "Create amazing diagrams", - "feature1Desc": "Design beautiful, enterprise-grade architecture visually.", - "feature2Title": "Use AI", - "feature2Desc": "Generate complete architectures with a single intelligent prompt.", - "feature3Title": "Code to diagram", - "feature3Desc": "Instantly construct stunning visual infrastructure from text.", - "feature4Title": "Export in many formats", - "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", - "analyticsTitle": "Anonymous Analytics", - "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts." + "feature1Title": "Harika diyagramlar oluşturun", + "feature1Desc": "Güzel, kurumsal düzeyde mimariyi görsel olarak tasarlayın.", + "feature2Title": "Yapay zeka kullanın", + "feature2Desc": "Tek bir akıllı komutla tam mimariler oluşturun.", + "feature3Title": "Koddan diyagrama", + "feature3Desc": "Metinden anında muhteşem görsel altyapı oluşturun.", + "feature4Title": "Birçok formatta dışa aktarın", + "feature4Desc": "Tamamen animasyonlu sunum diyagramlarına dışa aktarın.", + "analyticsTitle": "Anonim Analitik", + "analyticsDesc": "Tanı verileri topluyoruz. Diyagramlarınızı veya komutlarınızı asla okumuyoruz.", + "shortcutCommandBar": "Komut merkezini aç", + "shortcutHelp": "Klavye kısayollarını görüntüle", + "shortcutCanvas": "Tuvalde düğüm ekle", + "shortcutsTitle": "Kısayollarla hızlı başla", + "shortcutsBadge": "Klavye öncelikli" }, "footer": { "mitLicensed": "MIT Lisanslı" @@ -470,7 +487,7 @@ "description": "Nihai beyaz etiketli tuval. Tamamen özelleştirilebilir düğümler, kenarlar ve temalar — React Flow ile güçlendirilmiş. Bu sizin markanız, nefes almak için sonsuz alan verilmiş.", "diagramAsCode": "Kod Olarak Diyagram", "diagramAsCodeDesc": "Mermaid.js ve tip güvenli DSL'imiz için birinci sınıf destek. Mimarinizi kodla tanımlayın, JSON olarak dışa aktarın ve motorun düzeni halletmesine izin verin.", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot Yapay Zeka", "aiAssistant": "Yapay Zeka Asistanı", "flowpilotAIDesc": "Yönlendirilmiş AI düzenlemeleriyle diyagramınız üzerinde çalışın. \"Köşeleri daha yuvarlak yap\", \"Yük dengeleyici ekle\".", "addRedisCache": "Veritabanının önüne Redis önbelleği ekle.", @@ -528,7 +545,7 @@ "communityDesc": "OpenFlowKit üzerinde çalışan geliştiricilere katılın.", "roadmap": "Yol Haritası", "coreRenderer": "Çekirdek Render", - "flowpilotAI": "Flowpilot" + "flowpilotAI": "Flowpilot Yapay Zeka" }, "demo": { "livePreview": "Canlı Önizleme", @@ -548,12 +565,12 @@ "greeting": "Merhaba, size nasıl yardımcı olabilirim?", "tagline": "Akıllı rehberiniz", "messagePlaceholder": "Mesaj", - "aiSuffix": "AI...", + "aiSuffix": "Yapay Zeka...", "sendMessage": "Mesaj gönder", "newChat": "Yeni Sohbet", "docsTitle": "Dökümanlar", "aiAssistant": "AI Asistan", - "aiName": "AI", + "aiName": "Yapay Zeka", "you": "Siz", "searchingDocs": "Dökümanlar aranıyor...", "aiDisclaimer": "AI hata yapabilir. Önemli bilgileri doğrulayın.", @@ -590,7 +607,7 @@ "userRegistrationPrompt": "E-posta doğrulamalı kullanıcı kayıt akışı", "ecommerceCheckout": "E-Ticaret Ödeme", "ecommerceCheckoutPrompt": "Ödeme geçidi hata işlemeli e-ticaret ödeme süreci", - "cicdPipeline": "CI/CD Pipeline", + "cicdPipeline": "CI/CD Hattı", "cicdPipelinePrompt": "CI/CD pipeline mimarisi", "oauth2Login": "OAuth2 Girişi", "oauth2LoginPrompt": "OAuth2 giriş akışı" @@ -602,8 +619,8 @@ "noResults": "Düğüm bulunamadı", "untitled": "İsimsiz Düğüm", "type": "Tür", - "showingCount": "Showing: {{count}}", - "totalCount": "Total on canvas: {{count}}" + "showingCount": "Gösterilen: {{count}}", + "totalCount": "Tuvaldeki toplam: {{count}}" }, "templates": { "title": "Şablonlar", @@ -658,7 +675,7 @@ "orthogonalSpacious": "Geniş", "orthogonalSpaciousDesc": "Sunumlar ve incelemelerde daha fazla netlik için ek boşluk sunar.", "applyLayout": "Düzeni Uygula", - "layoutStyle": "Layout Style" + "layoutStyle": "Düzen Stili" }, "designSystem": { "title": "Tasarım Sistemleri", @@ -669,7 +686,7 @@ "visuals": { "title": "Bağlantı Stilleri", "edgeStyle": "Kenar Stili", - "bezier": "Bezier", + "bezier": "Eğri", "bezierDesc": "Yumuşak eğriler", "straight": "Düz", "straightDesc": "Doğrudan çizgiler", @@ -684,13 +701,13 @@ "animatedEdges": "Animasyonlu Kenarlar", "animatedEdgesDesc": "Akan parçacıklar", "strokeWidth": "Çizgi Kalınlığı", - "largeGraphSafety": "Large Graph Safety", - "largeGraphSafetyAuto": "Auto", - "largeGraphSafetyOn": "On", - "largeGraphSafetyOff": "Off", - "exportModeDeterministic": "Deterministic", - "exportModeLegacy": "Legacy", - "exportMode": "Export Mode" + "largeGraphSafety": "Büyük Graf Güvenliği", + "largeGraphSafetyAuto": "Otomatik", + "largeGraphSafetyOn": "Büyük Grafik Güvenliği Açık", + "largeGraphSafetyOff": "Kapalı", + "exportModeDeterministic": "Kesin", + "exportModeLegacy": "Eski", + "exportMode": "Dışa Aktarma Modu" }, "aiStudio": { "placeholders": { @@ -745,13 +762,14 @@ "sql": "CREATE TABLE ifadelerini buraya yapıştırın...", "infra": "Terraform state JSON, Kubernetes YAML, Docker Compose veya Terraform HCL içeriğini buraya yapıştırın...", "openapi": "OpenAPI / Swagger YAML ya da JSON içeriğinizi buraya yapıştırın...", - "code": "Kaynak kodunuzu buraya yapıştırın..." + "code": "Kaynak kodunuzu buraya yapıştırın...", + "mermaid": "Mermaid diyagram kodunu buraya yapıştırın..." }, "infraFormats": { - "terraformState": "Terraform State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "Terraform Durumu", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", - "terraformHcl": "Terraform HCL (AI)" + "terraformHcl": "Terraform HCL (YZ)" }, "errors": { "inputTooLarge": "Girdi boyutu {{size}} - yapıştırma için en fazla {{max}} olabilir.", @@ -765,16 +783,19 @@ }, "categories": { "sql": "SQL", - "infra": "Infra", + "infra": "Altyapı", "openapi": "OpenAPI", - "code": "Code", - "codebase": "Depo" + "code": "Kod", + "codebase": "Depo", + "mindmap": "Zihin Haritası", + "markdown": "Markdown" }, "title": "Veriden içe aktar", "description": "Kod, altyapı, SQL veya API özelliklerini diyagramınıza içe aktarın.", "uploadFile": "Dosya yükle", "parsing": "Ayrıştırılıyor...", "parse": "Ayrıştır", + "parseNativeProject": "Yerel Diyagram Oluştur", "analyzing": "Analiz ediliyor...", "aiActions": { "generateErd": "ER diyagramı oluştur (YZ)", @@ -825,34 +846,32 @@ "settingsModal": { "title": "Ayarlar", "general": "Genel", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot Yapay Zeka", "shortcuts": "Kısayollar", "running": "{appName} Çalışıyor", "generalSettings": "Genel Ayarlar", "flowpilotConfigurations": "Flowpilot Yapılandırması", "keyboardShortcuts": "Klavye Kısayolları", "canvas": { - "title": "Tuval", - "showGrid": "Izgara Göster", - "showGridDesc": "Tuval üzerinde nokta ızgarası göster", - "snapToGrid": "Izgaraya Yapış", - "snapToGridDesc": "Düğümleri taşırken ızgaraya hizala", - "miniMap": "Mini Harita", - "miniMapDesc": "Sağ altta mini harita göster", - "architectureStrictMode": "Mimari Katı Mod", - "architectureStrictModeDesc": "Mimari tanıları toparlama/doğrulama sorunları içerdiğinde Mermaid içe aktarmayı engeller", - "alignmentGuides": "Hizalama kılavuzları", - "alignmentGuidesDesc": "Düğümleri sürüklerken akıllı kılavuz çizgilerini göster", + "title": "Canvas", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", "routingProfile": "Routing Profile", - "routingProfileStandard": "Standard", - "routingProfileInfrastructure": "Infrastructure", - "routingProfileHint": "Infrastructure mode biases orthogonal routes for service maps.", - "edgeBundling": "Bundle Sibling Edges", - "edgeBundlingDesc": "Keep parallel connections on shared lanes" + "routingProfileStandard": "Standart", + "routingProfileInfrastructure": "Altyapı", + "routingProfileHint": "Altyapı modu, hizmet haritaları için ortogonal rotaları tercih eder.", + "edgeBundling": "Kardeş Kenarları Grupla", + "edgeBundlingDesc": "Paralel bağlantıları paylaşılan şeritlerde tut", + "architectureStrictMode": "Mimari Katı Modu", + "architectureStrictModeDesc": "Mimari tanılamalar kurtarma/doğrulama sorunları içerdiğinde Mermaid içe aktarmayı engelle" }, "ai": { "provider": "Sağlayıcı", - "model": "Model", + "model": "Yapay Zeka Modeli", "apiKey": "API Anahtarı", "customBaseUrl": "Özel Taban URL", "optional": "İsteğe bağlı", @@ -918,26 +937,40 @@ "category": "Akıl Yürütme" }, "gemini-3-flash": { - "label": "3 Flash", + "label": "Gemini 3 Flash", "hint": "Sınır hızı + zeka", - "category": "Önceki", + "category": "Eski", "badge": "Yeni" }, "gemini-3-pro": { - "label": "3 Pro", + "label": "Gemini 3 Pro", "hint": "En güçlü · Çok modlu", - "category": "Önceki", + "category": "Eski", "badge": "Yeni" + }, + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } } }, "openai": { "gpt-5-mini": { - "label": "GPT-5 mini", + "label": "GPT-5 Mini", "hint": "Hızlı · Maliyet verimli", "category": "Hız", "badge": "Varsayılan" }, "gpt-5": { + "2": { + "label": "GPT-5.2" + }, "label": "GPT-5", "hint": "Amiral gemisi · En yetenekli", "category": "Amiral Gemisi" @@ -949,13 +982,13 @@ "badge": "Yeni" }, "o4-mini": { - "label": "o4-mini", + "label": "O4-Mini", "hint": "Gelişmiş akıl yürütme · Hızlı", "category": "Akıl Yürütme", "badge": "Akıl Yürütme" }, "o3": { - "label": "o3", + "label": "O3", "hint": "Derin akıl yürütme · Karmaşık görevler", "category": "Akıl Yürütme", "badge": "Akıl Yürütme" @@ -999,7 +1032,7 @@ "badge": "Ücretsiz" }, "qwen/qwen3-32b": { - "label": "Qwen3 32B", + "label": "Qwen 3 32B", "hint": "Gelişmiş akıl yürütme · Araç kullanımı", "category": "Akıl Yürütme" }, @@ -1008,6 +1041,11 @@ "hint": "Çok yönlü model", "category": "Performans", "badge": "Performans" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } } }, "nvidia": { @@ -1022,7 +1060,7 @@ "category": "Hız" }, "deepseek/deepseek-v3-2": { - "label": "DeepSeek-V3.2 (685B)", + "label": "DeepSeek V3-2", "hint": "Son sürüm · GPT-5 seviyesinde", "category": "Amiral Gemisi", "badge": "Yeni" @@ -1040,19 +1078,19 @@ }, "cerebras": { "gpt-oss-120b": { - "label": "GPT-OSS 120B", + "label": "GPT OSS 120B", "hint": "120B parametre · WSE-3'te hızlı", "category": "Hız", "badge": "Varsayılan" }, "qwen-3-32b": { - "label": "Qwen3 32B", + "label": "Qwen 3 32B", "hint": "2.403 jeton/sn · Endüstrinin en hızlısı", "category": "Hız", - "badge": "🚀 En Hızlı" + "badge": "En Hızlı" }, "qwen-3-235b-a22b": { - "label": "Qwen3 235B A22B", + "label": "Qwen 3 235B", "hint": "Amiral gemisi · En iyi kalite", "category": "Amiral Gemisi", "badge": "Amiral Gemisi" @@ -1061,6 +1099,11 @@ "label": "Zai-GLM 4.7", "hint": "Gelişmiş akıl yürütme · Araç kullanımı", "category": "Akıl Yürütme" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } } }, "mistral": { @@ -1121,7 +1164,7 @@ "hint": "Yerel · Ücretsiz" }, "together": { - "name": "Together.ai", + "name": "Together AI", "hint": "Bulut · Hızlı" } }, @@ -1130,19 +1173,19 @@ "customEndpointTitle": "Özel endpoint nedir?", "customModelHint": "Endpoint'iniz için tam model kimliğini girin", "privacyTitle": "Gizlilik ve Şifreleme", - "advancedEndpointOverride": "Advanced Base URL Override", - "baseUrlHint": "Leave empty to use provider default endpoint. Use this for your own proxy/worker URL.", - "resetEndpoint": "Reset to default", - "customHeadersTitle": "Custom Headers", - "customHeadersSubtitle": "Send extra headers for auth proxies like Cloudflare Access.", - "addHeader": "Add Header", - "cloudflarePreset": "Use Cloudflare Preset", - "customHeadersEmpty": "No custom headers configured.", - "customHeadersSecurity": "Header values are stored locally in your browser profile.", + "advancedEndpointOverride": "Gelişmiş Taban URL Geçersiz Kılma", + "baseUrlHint": "Sağlayıcı varsayılan uç noktasını kullanmak için boş bırakın. Kendi proxy/worker URL'niz için bunu kullanın.", + "resetEndpoint": "Varsayılana sıfırla", + "customHeadersTitle": "Özel Başlıklar", + "customHeadersSubtitle": "Cloudflare Access gibi kimlik doğrulama vekilleri için ekstra başlıklar gönderin.", + "addHeader": "Başlık Ekle", + "cloudflarePreset": "Cloudflare Ön Ayarını Kullan", + "customHeadersEmpty": "Yapılandırılmış özel başlık yok.", + "customHeadersSecurity": "Başlık değerleri tarayıcı profilinizde yerel olarak saklanır.", "risk": { - "browserFriendly": "Browser-ready", - "proxyLikely": "Proxy likely", - "mixed": "Depends on endpoint" + "browserFriendly": "Tarayıcı uyumlu", + "proxyLikely": "Muhtemelen vekil sunucu gerekli", + "mixed": "Uç noktasına bağlı" } }, "brand": { @@ -1175,15 +1218,27 @@ "showBetaBadgeHint": "Logo yanında BETA çipini göster" }, "shortcutsHint": "İstediğiniz zaman ? tuşuna basarak bunları görüntüleyebilirsiniz.", - "settings": "Settings", - "canvasSettings": "Canvas Settings", - "description": "Configure canvas preferences and keyboard shortcuts.", - "close": "Close settings", - "closeDialog": "Close settings dialog", + "settings": "Ayarlar", + "canvasSettings": "Tuval Ayarları", + "description": "Tuval tercihlerini ve klavye kısayollarını yapılandırın.", + "close": "Ayarları kapat", + "closeDialog": "Ayarlar iletişim kutusunu kapat", "analytics": { "enableTitle": "Anonim başlatma analitiği", "enableDescription": "Anonim temel kullanım verilerini paylaş (isteğe bağlı)" - } + }, + "search": "Ara...", + "appearance": "Görünüm", + "account": "Hesap", + "about": "Hakkında", + "language": "Dil", + "theme": "Tema", + "fontSize": "Yazı boyutu", + "fontFamily": "Yazı tipi", + "save": "Kaydet", + "cancel": "İptal", + "reset": "Sıfırla", + "confirm": "Onayla" }, "customNodes": { "browserContent": "Tarayıcı İçeriği", @@ -1216,7 +1271,7 @@ "clearCanvas": "Tuvali Temizle", "undo": "Geri Al (Ctrl+Z)", "redo": "Yinele (Ctrl+Y)", - "commandCenter": "Open Command Center" + "commandCenter": "Komut Merkezini Aç" }, "flowEditor": { "cannotCloseLastTab": "Son sekmeyi kapatamazsınız.", @@ -1234,7 +1289,7 @@ "browseTemplates": "Şablonlara Gözat", "addBlankNode": "Boş Şekil Ekle" }, - "dslExportSkippedEdges": "{{count}} invalid edge(s) were skipped in DSL export." + "dslExportSkippedEdges": "DSL dışa aktarmada {{count}} geçersiz kenar atlandı." }, "annotationNode": { "placeholder": "*Düzenlemek için çift tıklayın*" @@ -1252,7 +1307,8 @@ "note": "Yapışkan Not", "noteDesc": "Dokümantasyon", "releaseToConnect": "Bağlamak için bırak", - "close": "Close connect menu" + "close": "Bağlantı menüsünü kapat", + "label": "Düğüm Bağlantı Menüsü" }, "errorBoundary": { "title": "Bir şeyler yanlış gitti", @@ -1277,11 +1333,16 @@ "deleteVersion": "Sürümü sil", "nodes": "{{count}} düğüm", "edges": "{{count}} bağlantı", - "close": "Close snapshots panel", + "close": "Anlık görüntü panelini kapat", "namedVersions": "Adlandırılmış sürümler", "noNamedSnapshots": "Henüz adlandırılmış sürüm yok.", "autosavedVersions": "Otomatik kaydedilen kontrol noktaları", - "noAutoSnapshots": "Henüz otomatik kaydedilen kontrol noktası yok." + "noAutoSnapshots": "Henüz otomatik kaydedilen kontrol noktası yok.", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "Akış Şablonları", @@ -1309,31 +1370,6 @@ "noSelection": "Hiçbir şey seçili değil", "selectHint": "Özelliklerini düzenlemek için bir düğüme veya kenara tıklayın" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "Seçim özeti" - }, "flowCanvas": { "strictModePasteBlocked": "Mimari Katı Mod, Mermaid yapıştırmayı engelledi. Kod görünümünü açın, tanıları düzeltin ve tekrar deneyin." }, @@ -1342,45 +1378,117 @@ "newFlowTab": "Yeni Sayfa" }, "share": { - "close": "Close", - "title": "Tasarımı paylaş", + "close": "Kapat", + "title": "Paylaş", "betaBadge": "Beta", - "description": "İş birlikçileri bu akışı sizinle birlikte gerçek zamanlı görüntülemeye ve düzenlemeye davet edin.", - "roomId": "Room ID", - "link": "Share link", - "copied": "Copied Link!", + "description": "Bu tuvali paylaş", + "roomId": "Oda Kimliği", + "link": "Bağlantı paylaş", + "copied": "Bağlantı Kopyalandı!", "copyLink": "Bağlantıyı kopyala", "footerNote": "Bu odayı paylaşmadığınız sürece diyagramınız yerel kalır. Kopyalama engellenirse yukarıdaki bağlantıyı manuel olarak kopyalayın.", "closeDialog": "Paylaşım iletişim kutusunu kapat", "status": { "cache": { - "syncing": " local cache syncing", - "ready": " local cache ready", - "hydrated": " restored from local cache" + "syncing": " yerel önbellek senkronize ediliyor", + "ready": " yerel önbellek hazır", + "hydrated": " yerel önbellekten geri yüklendi" }, "realtime": "Gerçek zamanlı eşler arası senkronizasyon", "waiting": "Gerçek zamanlı senkronizasyona bağlanılıyor", "fallback": "Yalnızca yerel mod" }, - "openDialog": "Share dialog", + "openDialog": "Paylaşım diyaloğu", "toast": { - "fallbackMode": "Realtime sync is unavailable. Continuing in local-only mode.", - "reconnected": "Realtime collaboration restored.", + "fallbackMode": "Gerçek zamanlı senkronizasyon kullanılamıyor. Yalnızca yerel modda devam ediliyor.", + "reconnected": "Gerçek zamanlı iş birliği geri yüklendi.", "copyFailed": "Paylaşım bağlantısı kopyalanamadı.", "linkCopied": "İş birliği bağlantısı kopyalandı.", - "copyManual": "Clipboard access is blocked. Copy the link manually from the share dialog." - } + "copyManual": "Pano erişimi engellendi. Bağlantıyı paylaşım diyaloğundan manuel olarak kopyalayın." + }, + "embed": "Göm", + "embedCode": "Gömme kodu", + "export": "Dışa aktar", + "settings": "Paylaşım ayarları", + "anyoneWithLink": "Bağlantısı olan herkes", + "viewOnly": "Yalnızca görüntüleme", + "canEdit": "Düzenleyebilir", + "disable": "Paylaşımı kapat", + "enable": "Paylaşımı aç", + "invite": "Davet et", + "pending": "Beklemede", + "revoke": "İptal et", + "expired": "Süresi doldu" }, "connectionPanel": { "architecture": "Mimari", - "label": "Label", + "label": "Etiket", "messagePlaceholder": "Mesaj", - "route": "Route", - "appearance": "Appearance", + "route": "Yol", + "appearance": "Görünüm", "condition": "Koşul", "deleteConnection": "Bağlantıyı sil" }, "sidebar": { - "close": "Kenar çubuğunu kapat" + "close": "Kenar çubuğunu kapat", + "searchPlaceholder": "Ara...", + "noResults": "Sonuç yok", + "nodes": "Düğümler", + "components": "Bileşenler", + "snippets": "Parçacıklar", + "addons": "Eklentiler" + }, + "contextMenu": { + "label": "Tuval Bağlam Menüsü" + }, + "canvas": { + "addNodeShortcut": "Düğüm ekle", + "aiChatPlaceholder": "Bir şeyler oluştur...", + "nodes": "Düğümler", + "connections": "Bağlantılar", + "elements": "Öğeler", + "selection": "Seçim", + "noSelection": "Seçim yok", + "alignNodes": "Düğümleri hizala", + "distributeNodes": "Düğümleri dağıt", + "alignLeft": "Sola hizala", + "alignCenter": "Merkeze hizala", + "alignRight": "Sağa hizala", + "alignTop": "Üste hizala", + "alignMiddle": "Ortaya hizala", + "alignBottom": "Alta hizala", + "distributeHorizontally": "Yatay dağıt", + "distributeVertically": "Dikey dağıt", + "zoomToFit": "Sığdırmak için yakınlaştır", + "zoomToSelection": "Seçime yakınlaştır", + "locked": "Kilitli", + "unlock": "Kilidi aç", + "lock": "Kilitle", + "bringToFront": "Öne getir", + "sendToBack": "Arkaya gönder", + "group": "Grupla", + "ungroup": "Grubu kaldır" + }, + "mindmap": { + "addChild": "Alt konu ekle", + "addSibling": "Kardeş konu ekle", + "addParent": "Üst konu ekle", + "delete": "Sil", + "insertAfter": "Sonra ekle", + "insertBefore": "Önce ekle" + }, + "aiModel": { + "title": "AI Modeli", + "provider": "Sağlayıcı", + "model": "Model", + "temperature": "Sıcaklık", + "maxTokens": "Maksimum belirteç", + "buttons": { + "retry": "Tekrar dene", + "stop": "Durdur", + "clear": "Temizle" + }, + "thinking": "Düşünüyor...", + "error": "AI hatası" } } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 2dd1679..eee38fe 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -141,12 +141,14 @@ "gif": "回放 GIF", "hintPlaybackGif": "适用于文档/社交媒体的短循环", "share": "分享实时画布", + "shareEmbed": "分享与嵌入", "hintShareViewer": "此房间的邀请链接", + "hintShareEmbed": "只读查看链接", "readmeEmbed": "README Embed", "hintReadmeEmbed": "Copy Markdown snippet", "sectionImage": "Image", - "sectionVideo": "Video & Animation", - "sectionCode": "Code & Data", + "sectionVideo": "视频", + "sectionCode": "代码", "shareSection": "分享画布", "revealVideo": "Reveal Video", "hintRevealVideo": "Nodes fade in sequentially (WebM/MP4)", @@ -240,6 +242,7 @@ } }, "home": { + "appName": "开放流程工具包", "title": "仪表板", "description": "管理您的流程和图表。", "recentFiles": "最近文件", @@ -263,7 +266,22 @@ "confirmation": "删除“{{name}}”?", "hint": "除非您有导出的备份或另一份副本,否则此操作无法撤销。", "closeDialog": "关闭删除流程对话框" - } + }, + "suggestionBlank": "空白画布", + "suggestionBlankDesc": "直接进入编辑器", + "suggestionAI": "流程领航人工智能", + "suggestionAIDesc": "从提示开始", + "suggestionImport": "导入", + "suggestionImportDesc": "导入现有工作", + "suggestionTemplates": "模板", + "suggestionTemplatesDesc": "从经过验证的模式开始", + "continueTitle": "继续最近的操作", + "homeEmptyTitle": "创建您的第一个流程", + "homeEmptySubtitle": "即时设计企业级架构。从空白画布开始,用我们的AI构建器描述您的基础设施,或使用定制模板。", + "homeBlankCanvas": "空白画布", + "homeFlowpilotAI": "流程领航人工智能", + "homeTemplates": "模板", + "homeImportFile": "或导入现有文件" }, "settings": { "title": "设置", @@ -295,33 +313,29 @@ "help": "帮助" }, "properties": { - "title": "属性", - "nodeType": "节点类型", - "label": "标签", - "description": "描述", - "color": "颜色", - "icon": "图标", - "size": "大小", - "shape": "形状", - "bulkShape": "批量形状", - "bulkColor": "批量颜色", - "bulkIcon": "批量图标", - "labelTransform": "标签变换", - "prefixOptional": "前缀(可选)", - "suffixOptional": "后缀(可选)", - "findReplace": "查找和替换", - "findLabel": "查找", - "findPlaceholder": "要查找的文本", - "replaceLabel": "替换为", - "replacePlaceholder": "替换文本", - "useRegex": "使用正则表达式", - "previewSummary": "预览摘要", - "bulkApplySummary": "将更新已选择的 {{count}} 个项目", - "selectFieldToApply": "请至少选择一个要应用的字段。", - "applyToSelectedNodes": "应用到所选项目", - "imageSettings": "图像设置", - "transparency": "透明度", - "rotation": "旋转" + "title": "Properties", + "shape": "Shape", + "color": "Color", + "icon": "Icon", + "rotation": "Rotation", + "transparency": "Transparency", + "imageSettings": "Image Settings", + "bulkShape": "Bulk Shape", + "bulkColor": "Bulk Color", + "bulkIcon": "Bulk Icon", + "labelTransform": "Label Transform", + "findReplace": "Find & Replace", + "findLabel": "Find", + "findPlaceholder": "Find text", + "replaceLabel": "Replace", + "replacePlaceholder": "Replace with", + "prefixOptional": "Prefix (optional)", + "suffixOptional": "Suffix (optional)", + "useRegex": "Use Regex", + "applyToSelectedNodes": "Apply to selected nodes", + "selectFieldToApply": "Select a field to apply", + "previewSummary": "Preview summary", + "selectionSummary": "选择摘要" }, "saveStatus": { "saved": "已保存" @@ -346,7 +360,9 @@ "title": "历史记录", "undo": "撤销", "redo": "重做", - "clear": "清除历史记录" + "clear": "清除历史记录", + "undoUnavailable": "目前没有可撤销的操作。", + "redoUnavailable": "目前没有可重做的操作。" }, "errors": { "generic": "出现了错误", @@ -378,7 +394,12 @@ "feature4Desc": "Export into beautiful, fully animated presentation diagrams.", "analyticsTitle": "Anonymous Analytics", "analyticsDesc": "We collect diagnostic data. We never read your diagrams or prompts.", - "getStarted": "Get Started" + "getStarted": "Get Started", + "shortcutCommandBar": "打开命令中心", + "shortcutHelp": "查看键盘快捷键", + "shortcutCanvas": "在画布上添加节点", + "shortcutsTitle": "使用快捷键快速开始", + "shortcutsBadge": "键盘优先" }, "footer": { "mitLicensed": "MIT 开源协议" @@ -437,7 +458,7 @@ "description": "终极白标画布。", "diagramAsCode": "代码即图表", "diagramAsCodeDesc": "支持 Mermaid.js 和 DSL。", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot 人工智能", "aiAssistant": "AI 助手", "flowpilotAIDesc": "通过引导式 AI 编辑来完善你的图表。", "addRedisCache": "在数据库前添加一个 Redis 缓存。", @@ -495,7 +516,7 @@ "communityDesc": "加入构建者行列。", "roadmap": "路线图", "coreRenderer": "核心渲染器", - "flowpilotAI": "Flowpilot" + "flowpilotAI": "Flowpilot 人工智能" }, "demo": { "livePreview": "实时预览", @@ -618,7 +639,7 @@ "left": "向左", "spacing": "间距", "compact": "紧凑", - "normal": "正常", + "normal": "普通", "loose": "宽松", "orthogonalCompact": "紧凑", "orthogonalCompactDesc": "适合中高密度图表的紧凑型从左到右结构。", @@ -653,7 +674,7 @@ "strokeWidth": "线宽", "largeGraphSafety": "大图保护", "largeGraphSafetyAuto": "自动", - "largeGraphSafetyOn": "开启", + "largeGraphSafetyOn": "大图安全开启", "largeGraphSafetyOff": "关闭", "exportModeDeterministic": "确定性", "exportModeLegacy": "旧版", @@ -712,11 +733,12 @@ "sql": "请在此粘贴 CREATE TABLE 语句...", "infra": "请在此粘贴 Terraform state JSON、Kubernetes YAML、Docker Compose 或 Terraform HCL...", "openapi": "请在此粘贴你的 OpenAPI / Swagger YAML 或 JSON...", - "code": "请在此粘贴你的源代码..." + "code": "请在此粘贴你的源代码...", + "mermaid": "请在此粘贴 Mermaid 图表代码..." }, "infraFormats": { - "terraformState": "Terraform State (.tfstate)", - "kubernetes": "Kubernetes YAML", + "terraformState": "Terraform状态", + "kubernetes": "Kubernetes", "dockerCompose": "Docker Compose", "terraformHcl": "Terraform HCL (AI)" }, @@ -735,13 +757,16 @@ "infra": "Infra", "openapi": "OpenAPI", "code": "Code", - "codebase": "仓库" + "codebase": "仓库", + "mindmap": "思维导图", + "markdown": "Markdown" }, "title": "从数据导入", "description": "将代码、基础设施、SQL 或 API 规格导入到你的图表中。", "uploadFile": "上传文件", "parsing": "解析中...", "parse": "解析", + "parseNativeProject": "Generate Native Diagram", "analyzing": "分析中...", "aiActions": { "generateErd": "生成 ERD(AI)", @@ -792,34 +817,32 @@ "settingsModal": { "title": "设置", "general": "通用", - "flowpilotAI": "Flowpilot", + "flowpilotAI": "Flowpilot 人工智能", "shortcuts": "快捷键", "running": "正在运行 {appName}", "generalSettings": "通用设置", "flowpilotConfigurations": "Flowpilot 配置", "keyboardShortcuts": "键盘快捷键", "canvas": { - "title": "画布", - "showGrid": "显示网格", - "showGridDesc": "在画布上显示点状网格", - "snapToGrid": "对齐网格", - "snapToGridDesc": "移动时自动对齐", - "miniMap": "小地图", - "miniMapDesc": "右下角显示小地图", - "architectureStrictMode": "架构严格模式", - "architectureStrictModeDesc": "当架构诊断包含恢复/校验问题时,阻止 Mermaid 导入", - "alignmentGuides": "对齐参考线", - "alignmentGuidesDesc": "拖动节点时显示智能参考线", - "routingProfile": "路由配置", + "title": "Canvas", + "showGrid": "Show Grid", + "showGridDesc": "Display a dot grid on the canvas", + "snapToGrid": "Snap to Grid", + "snapToGridDesc": "Snap nodes to the grid when moving", + "alignmentGuides": "Alignment Guides", + "alignmentGuidesDesc": "Show smart guide lines while dragging nodes", + "routingProfile": "Routing Profile", "routingProfileStandard": "标准", "routingProfileInfrastructure": "基础设施", - "routingProfileHint": "基础设施模式会优先为服务图使用正交线路。", - "edgeBundling": "捆绑平行边", - "edgeBundlingDesc": "让平行连接保持在共享通道上" + "routingProfileHint": "基础设施模式偏好服务地图的正交路由。", + "edgeBundling": "捆绑兄弟边", + "edgeBundlingDesc": "将并行连接保持在共享车道上", + "architectureStrictMode": "架构严格模式", + "architectureStrictModeDesc": "当架构诊断包含恢复/验证问题时阻止Mermaid导入" }, "ai": { "provider": "提供商", - "model": "模型", + "model": "AI模型", "apiKey": "API 密钥", "customBaseUrl": "自定义 URL", "optional": "可选", @@ -886,6 +909,135 @@ "browserFriendly": "浏览器友好", "proxyLikely": "可能需要代理", "mixed": "取决于端点" + }, + "models": { + "gemini": { + "gemini-2": { + "5-flash-lite": { + "label": "Gemini 2.5 Flash Lite" + }, + "5-flash": { + "label": "Gemini 2.5 Flash" + }, + "5-pro": { + "label": "Gemini 2.5 Pro" + } + }, + "gemini-3-flash": { + "label": "Gemini 3 Flash" + }, + "gemini-3-pro": { + "label": "Gemini 3 Pro" + } + }, + "openai": { + "gpt-5-mini": { + "label": "GPT-5 Mini" + }, + "gpt-5": { + "2": { + "label": "GPT-5.2" + }, + "label": "GPT-5" + }, + "o4-mini": { + "label": "O4-Mini" + }, + "o3": { + "label": "O3" + } + }, + "claude": { + "claude-haiku-4-5": { + "label": "Claude Haiku 4.5" + }, + "claude-sonnet-4-5": { + "label": "Claude Sonnet 4.5" + }, + "claude-sonnet-4-6": { + "label": "Claude Sonnet 4.6" + }, + "claude-opus-4-6": { + "label": "Claude Opus 4.6" + } + }, + "groq": { + "meta-llama/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "meta-llama/llama-4-maverick-17b-128e-instruct": { + "label": "Llama 4 Maverick" + }, + "qwen/qwen3-32b": { + "label": "Qwen 3 32B" + }, + "llama-3": { + "3-70b-versatile": { + "label": "Llama 3.3 70B" + } + } + }, + "nvidia": { + "meta/llama-4-scout-17b-16e-instruct": { + "label": "Llama 4 Scout" + }, + "nvidia/nemotron-nano-12b-v2-vl": { + "label": "Nemotron Nano 12B" + }, + "deepseek/deepseek-v3-2": { + "label": "DeepSeek V3-2" + }, + "qwen/qwq-32b": { + "label": "QwQ 32B" + }, + "moonshotai/kimi-k2-thinking": { + "label": "Kimi K2 Thinking" + } + }, + "cerebras": { + "gpt-oss-120b": { + "label": "GPT OSS 120B" + }, + "qwen-3-32b": { + "label": "Qwen 3 32B" + }, + "qwen-3-235b-a22b": { + "label": "Qwen 3 235B" + }, + "zai-glm-4": { + "7": { + "label": "Zai GLM 4.7" + } + } + }, + "mistral": { + "mistral-small-latest": { + "label": "Mistral Small" + }, + "mistral-medium-latest": { + "label": "Mistral Medium" + }, + "mistral-large-latest": { + "label": "Mistral Large" + }, + "codestral-latest": { + "label": "Codestral" + }, + "pixtral-large-latest": { + "label": "Pixtral Large" + } + } + }, + "customEndpoints": { + "ollama": { + "name": "Ollama" + }, + "lmStudio": { + "name": "LM Studio" + }, + "together": { + "name": "Together AI" + } } }, "brand": { @@ -905,8 +1057,8 @@ "tabType": "Type", "tabUI": "UI & Shape", "appName": "应用名称", - "logo": "Logo", - "favicon": "Favicon", + "logo": "标志", + "favicon": "网站图标", "logoStyle": "Logo 样式", "fontFamily": "字体系列", "googleFontsHint": "Dynamically loaded from Google Fonts", @@ -926,7 +1078,19 @@ "analytics": { "enableTitle": "匿名启动分析", "enableDescription": "共享匿名的基础使用数据(可选)" - } + }, + "search": "搜索...", + "appearance": "外观", + "account": "账户", + "about": "关于", + "language": "语言", + "theme": "主题", + "fontSize": "字体大小", + "fontFamily": "字体", + "save": "保存", + "cancel": "取消", + "reset": "重置", + "confirm": "确认" }, "customNodes": { "browserContent": "浏览器内容", @@ -995,7 +1159,8 @@ "note": "便利贴", "noteDesc": "文档说明", "releaseToConnect": "松开以连接", - "close": "关闭连接菜单" + "close": "关闭连接菜单", + "label": "节点连接菜单" }, "errorBoundary": { "title": "出现了错误", @@ -1024,7 +1189,12 @@ "namedVersions": "命名版本", "noNamedSnapshots": "还没有命名版本。", "autosavedVersions": "自动保存检查点", - "noAutoSnapshots": "还没有自动保存检查点。" + "noAutoSnapshots": "还没有自动保存检查点。", + "undoTimelinePosition": "Step {{current}} of {{total}} in the current history stack.", + "undoTimelineScrubber": "Scrub through recent undo history", + "undoTimeline": "Undo Timeline", + "undoTimelineAtEarliest": "You are at the earliest captured state.", + "undoTimelineAtLatest": "You are at the latest state." }, "templatesPanel": { "title": "流程模板", @@ -1052,31 +1222,6 @@ "noSelection": "未选择任何内容", "selectHint": "点击节点或连线以编辑其属性" }, - "properties": { - "title": "Properties", - "shape": "Shape", - "color": "Color", - "icon": "Icon", - "rotation": "Rotation", - "transparency": "Transparency", - "imageSettings": "Image Settings", - "bulkShape": "Bulk Shape", - "bulkColor": "Bulk Color", - "bulkIcon": "Bulk Icon", - "labelTransform": "Label Transform", - "findReplace": "Find & Replace", - "findLabel": "Find", - "findPlaceholder": "Find text", - "replaceLabel": "Replace", - "replacePlaceholder": "Replace with", - "prefixOptional": "Prefix (optional)", - "suffixOptional": "Suffix (optional)", - "useRegex": "Use Regex", - "applyToSelectedNodes": "Apply to selected nodes", - "selectFieldToApply": "Select a field to apply", - "previewSummary": "Preview summary", - "selectionSummary": "选择摘要" - }, "flowCanvas": { "strictModePasteBlocked": "架构严格模式已阻止 Mermaid 粘贴。请打开代码视图,修复诊断后重试。" }, @@ -1106,9 +1251,9 @@ }, "share": { "close": "Close", - "title": "分享设计", + "title": "分享", "betaBadge": "测试版", - "description": "邀请协作者与你一起实时查看和编辑此流程。", + "description": "分享此画布", "roomId": "房间 ID", "link": "分享链接", "copied": "Copied Link!", @@ -1132,7 +1277,20 @@ "copyFailed": "无法复制分享链接。", "linkCopied": "协作链接已复制。", "copyManual": "剪贴板访问被阻止。请从分享对话框中手动复制链接。" - } + }, + "embed": "嵌入", + "embedCode": "嵌入代码", + "export": "导出", + "settings": "分享设置", + "anyoneWithLink": "拥有链接的任何人", + "viewOnly": "仅查看", + "canEdit": "可以编辑", + "disable": "关闭分享", + "enable": "开启分享", + "invite": "邀请", + "pending": "待处理", + "revoke": "撤销", + "expired": "已过期" }, "connectionPanel": { "architecture": "架构", @@ -1144,6 +1302,65 @@ "deleteConnection": "删除连接" }, "sidebar": { - "close": "关闭侧边栏" + "close": "关闭侧边栏", + "searchPlaceholder": "搜索...", + "noResults": "无结果", + "nodes": "节点", + "components": "组件", + "snippets": "代码片段", + "addons": "插件" + }, + "contextMenu": { + "label": "画布右键菜单" + }, + "canvas": { + "addNodeShortcut": "添加节点", + "aiChatPlaceholder": "创建一些内容...", + "nodes": "节点", + "connections": "连接", + "elements": "元素", + "selection": "选择", + "noSelection": "无选择", + "alignNodes": "对齐节点", + "distributeNodes": "分布节点", + "alignLeft": "左对齐", + "alignCenter": "居中对齐", + "alignRight": "右对齐", + "alignTop": "顶部对齐", + "alignMiddle": "中间对齐", + "alignBottom": "底部对齐", + "distributeHorizontally": "水平分布", + "distributeVertically": "垂直分布", + "zoomToFit": "缩放以适应", + "zoomToSelection": "缩放到选择", + "locked": "已锁定", + "unlock": "解锁", + "lock": "锁定", + "bringToFront": "带到前面", + "sendToBack": "发送到后面", + "group": "分组", + "ungroup": "取消分组" + }, + "mindmap": { + "addChild": "添加子主题", + "addSibling": "添加同级主题", + "addParent": "添加父主题", + "delete": "删除", + "insertAfter": "在后面插入", + "insertBefore": "在前面插入" + }, + "aiModel": { + "title": "AI模型", + "provider": "提供商", + "model": "模型", + "temperature": "温度", + "maxTokens": "最大令牌数", + "buttons": { + "retry": "重试", + "stop": "停止", + "clear": "清除" + }, + "thinking": "思考中...", + "error": "AI错误" } } diff --git a/scripts/check-bundle-budget.mjs b/scripts/check-bundle-budget.mjs index f60d3d6..1bd8a6c 100644 --- a/scripts/check-bundle-budget.mjs +++ b/scripts/check-bundle-budget.mjs @@ -6,7 +6,7 @@ const INDEX_HTML_PATH = path.join(DIST_DIR, 'index.html'); const MAIN_JS_MAX_KB = Number(process.env.ENTRY_MAIN_JS_BUDGET_KB ?? 1400); const TOTAL_ENTRY_JS_MAX_KB = Number(process.env.ENTRY_TOTAL_JS_BUDGET_KB ?? 2800); -const ENTRY_CSS_MAX_KB = Number(process.env.ENTRY_CSS_BUDGET_KB ?? 220); +const ENTRY_CSS_MAX_KB = Number(process.env.ENTRY_CSS_BUDGET_KB ?? 230); const LAZY_CHUNK_MAX_KB = Number(process.env.LAZY_CHUNK_MAX_KB ?? 1500); const LAZY_TOTAL_MAX_KB = Number(process.env.LAZY_TOTAL_MAX_KB ?? 8000); diff --git a/src/components/FlowEditorPanels.tsx b/src/components/FlowEditorPanels.tsx index ea1d650..16db181 100644 --- a/src/components/FlowEditorPanels.tsx +++ b/src/components/FlowEditorPanels.tsx @@ -14,6 +14,7 @@ import type { FlowTemplate } from '@/services/templates'; import type { EdgeData, NodeData } from '@/lib/types'; import type { DomainLibraryItem } from '@/services/domainLibrary'; import type { SupportedLanguage } from '@/hooks/ai-generation/codeToArchitecture'; +import type { CodebaseAnalysis } from '@/hooks/ai-generation/codebaseAnalyzer'; import type { TerraformInputFormat } from '@/hooks/ai-generation/terraformToCloud'; import type { AIReadinessState } from '@/hooks/ai-generation/readiness'; @@ -89,7 +90,7 @@ export interface CommandBarPanelProps { onTerraformAnalysis?: (input: string, format: TerraformInputFormat) => Promise; onOpenApiAnalysis?: (spec: string) => Promise; onApplyDsl?: (dsl: string) => void; - onCodebaseAnalysis?: (summary: string) => Promise; + onCodebaseAnalysis?: (analysis: CodebaseAnalysis) => Promise; showGrid: boolean; onToggleGrid: () => void; snapToGrid: boolean; diff --git a/src/components/HomePage.integration.test.tsx b/src/components/HomePage.integration.test.tsx index e7c7511..12c23c7 100644 --- a/src/components/HomePage.integration.test.tsx +++ b/src/components/HomePage.integration.test.tsx @@ -6,6 +6,7 @@ import { useFlowStore } from '@/store'; import type { FlowTab } from '@/lib/types'; import type { FlowDocument } from '@/services/storage/flowDocumentModel'; import { WELCOME_MODAL_ENABLED_STORAGE_KEY, WELCOME_SEEN_STORAGE_KEY } from './home/welcomeModalState'; +import { recordOnboardingEvent } from '@/services/onboarding/events'; vi.mock('react-i18next', async (importOriginal) => { const actual = await importOriginal(); @@ -96,7 +97,7 @@ describe('HomePage integration flows', () => { expect(screen.queryByRole('button', { name: /Product Discovery Workshop Map/i })).toBeNull(); }); - it('exposes template and flowpilot entry points in the empty dashboard state', async () => { + it('exposes template and flowpilot entry points in the empty dashboard state', async () => { const onLaunchWithTemplates = vi.fn(); const onLaunchWithAI = vi.fn(); useFlowStore.setState({ @@ -117,6 +118,27 @@ describe('HomePage integration flows', () => { expect(onLaunchWithAI).toHaveBeenCalledTimes(1); }); + it('shows recent onboarding action suggestions in the empty dashboard', async () => { + useFlowStore.setState({ + documents: [], + activeDocumentId: '', + tabs: [], + activeTabId: null, + nodes: [], + edges: [], + }); + recordOnboardingEvent('welcome_prompt_selected', { source: 'welcome-modal' }); + recordOnboardingEvent('welcome_template_selected', { source: 'welcome-modal' }); + + await renderHomePage(); + + expect(screen.getByText('Continue with a recent action')).toBeTruthy(); + const suggestionPanel = screen.getByTestId('home-recent-actions'); + + expect(within(suggestionPanel).getByRole('button', { name: /Flowpilot AI/i })).toBeTruthy(); + expect(within(suggestionPanel).getByRole('button', { name: /Templates/i })).toBeTruthy(); + }); + it('opens persisted flows from the dashboard list', async () => { const onOpenFlow = vi.fn(); useFlowStore.setState({ diff --git a/src/components/StudioAIPanel.test.tsx b/src/components/StudioAIPanel.test.tsx index 09edd5f..f651ba0 100644 --- a/src/components/StudioAIPanel.test.tsx +++ b/src/components/StudioAIPanel.test.tsx @@ -202,4 +202,55 @@ describe('StudioAIPanel', () => { expect(screen.getByRole('button', { name: 'Edit current' })).toHaveAttribute('aria-pressed', 'true'); expect(screen.getByRole('button', { name: 'Create new' })).toHaveAttribute('aria-pressed', 'false'); }); + + it('shows preview copy for repo enhancement diffs', () => { + render( + + ); + + expect( + screen.getByText('Codebase enhancement ready — review the upgraded diagram.') + ).toBeInTheDocument(); + expect( + screen.getByText( + 'Started from the native repository map and layered in AI architecture improvements.' + ) + ).toBeInTheDocument(); + expect(screen.getByText('Platform: aws')).toBeInTheDocument(); + expect(screen.getByText('4 native sections')).toBeInTheDocument(); + }); }); diff --git a/src/components/StudioAIPanel.tsx b/src/components/StudioAIPanel.tsx index c794a7a..424e2c1 100644 --- a/src/components/StudioAIPanel.tsx +++ b/src/components/StudioAIPanel.tsx @@ -222,9 +222,26 @@ export function StudioAIPanel({

- {t('commandBar.aiStudio.importReady', 'Import ready - review changes')} + {pendingDiff.previewTitle}

+ {pendingDiff.previewDetail ? ( +

+ {pendingDiff.previewDetail} +

+ ) : null} + {pendingDiff.previewStats && pendingDiff.previewStats.length > 0 ? ( +
+ {pendingDiff.previewStats.map((stat) => ( + + {stat} + + ))} +
+ ) : null}
{pendingDiff.addedCount > 0 && ( diff --git a/src/components/StudioCodePanel.tsx b/src/components/StudioCodePanel.tsx index 4b93f0c..e35d0b4 100644 --- a/src/components/StudioCodePanel.tsx +++ b/src/components/StudioCodePanel.tsx @@ -1,5 +1,13 @@ import React, { useRef } from 'react'; -import { AlertCircle, BookOpen, CheckCircle2, CircleHelp, Play, RotateCcw, Zap } from 'lucide-react'; +import { + AlertCircle, + BookOpen, + CheckCircle2, + CircleHelp, + Play, + RotateCcw, + Zap, +} from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { Button } from './ui/Button'; import { Textarea } from './ui/Textarea'; @@ -9,280 +17,296 @@ import { useMermaidDiagnosticsActions } from '@/store/selectionHooks'; import { useToast } from './ui/ToastContext'; import type { FlowEdge, FlowNode } from '@/lib/types'; import type { StudioCodeMode } from '@/hooks/useFlowEditorUIState'; -import { useStudioCodePanelController, type DraftPreviewState } from './studio-code-panel/useStudioCodePanelController'; +import { + useStudioCodePanelController, + type DraftPreviewState, +} from './studio-code-panel/useStudioCodePanelController'; import { Tooltip } from './Tooltip'; interface CodeModeOption { - id: StudioCodeMode; - label: string; + id: StudioCodeMode; + label: string; } const MODE_OPTIONS: CodeModeOption[] = [ - { id: 'openflow', label: `${APP_NAME} DSL` }, - { id: 'mermaid', label: 'Mermaid' }, + { id: 'openflow', label: `${APP_NAME} DSL` }, + { id: 'mermaid', label: 'Mermaid' }, ]; function friendlyDslError(raw: string): string { - if (/unexpected token/i.test(raw)) return 'Syntax error, check for missing colons or brackets'; - if (/duplicate|already defined/i.test(raw)) return 'Duplicate node ID, each node must have a unique name'; - if (/spaces?\b.*id|id.*\bspaces?/i.test(raw) || /node id.*space/i.test(raw)) return 'Node IDs cannot contain spaces, use underscores (for example my_node)'; - return raw; + if (/unexpected token/i.test(raw)) return 'Syntax error, check for missing colons or brackets'; + if (/duplicate|already defined/i.test(raw)) + return 'Duplicate node ID, each node must have a unique name'; + if (/spaces?\b.*id|id.*\bspaces?/i.test(raw) || /node id.*space/i.test(raw)) + return 'Node IDs cannot contain spaces, use underscores (for example my_node)'; + return raw; } function getDraftPreviewToneClass(state: DraftPreviewState): string { - if (state === 'ready') { - return 'text-emerald-500'; - } + if (state === 'ready') { + return 'text-emerald-500'; + } - if (state === 'error') { - return 'text-amber-500'; - } + if (state === 'error') { + return 'text-amber-500'; + } - return 'text-[var(--brand-secondary)]'; + return 'text-[var(--brand-secondary)]'; } function getDraftPreviewBadgeClass(state: DraftPreviewState): string { - if (state === 'ready') { - return 'bg-emerald-500/10 text-emerald-500'; - } + if (state === 'ready') { + return 'bg-emerald-500/10 text-emerald-500'; + } - if (state === 'error') { - return 'bg-amber-500/10 text-amber-500'; - } + if (state === 'error') { + return 'bg-amber-500/10 text-amber-500'; + } - return 'bg-[var(--brand-background)] text-[var(--brand-secondary)]'; + return 'bg-[var(--brand-background)] text-[var(--brand-secondary)]'; } function getModeButtonClassName(isActive: boolean): string { - if (isActive) { - return 'border-[var(--brand-primary)] text-[var(--brand-primary)]'; - } + if (isActive) { + return 'border-[var(--brand-primary)] text-[var(--brand-primary)]'; + } - return 'border-transparent text-[var(--brand-secondary)] hover:text-[var(--brand-text)]'; + return 'border-transparent text-[var(--brand-secondary)] hover:text-[var(--brand-text)]'; } function getLivePreviewButtonClassName(isActive: boolean): string { - if (isActive) { - return 'border-[var(--brand-primary-200)] bg-[var(--brand-primary-50)] text-[var(--brand-primary)]'; - } + if (isActive) { + return 'border-[var(--brand-primary-200)] bg-[var(--brand-primary-50)] text-[var(--brand-primary)]'; + } - return 'border-[var(--color-brand-border)] text-[var(--brand-secondary)] hover:border-[var(--brand-primary-200)] hover:text-[var(--brand-text)]'; + return 'border-[var(--color-brand-border)] text-[var(--brand-secondary)] hover:border-[var(--brand-primary-200)] hover:text-[var(--brand-text)]'; } interface StudioCodePanelProps { - nodes: FlowNode[]; - edges: FlowEdge[]; - onApply: (nodes: FlowNode[], edges: FlowEdge[]) => void; - mode: StudioCodeMode; - onModeChange: (mode: StudioCodeMode) => void; + nodes: FlowNode[]; + edges: FlowEdge[]; + onApply: (nodes: FlowNode[], edges: FlowEdge[]) => void; + mode: StudioCodeMode; + onModeChange: (mode: StudioCodeMode) => void; } export function StudioCodePanel({ + nodes, + edges, + onApply, + mode, + onModeChange, +}: StudioCodePanelProps): React.ReactElement { + const { t } = useTranslation(); + const { activeTabId, updateTab, viewSettings } = useFlowStore(); + const { setMermaidDiagnostics, clearMermaidDiagnostics } = useMermaidDiagnosticsActions(); + const { addToast } = useToast(); + const textareaRef = useRef(null); + const { + code, + error, + diagnostics, + isApplying, + draftPreview, + hasDraftChanges, + liveSync, + setLiveSync, + handleCodeChange, + handleApply, + handleReset, + handleModeSelect, + } = useStudioCodePanelController({ nodes, edges, - onApply, mode, + onApply, onModeChange, -}: StudioCodePanelProps): React.ReactElement { - const { t } = useTranslation(); - const { activeTabId, updateTab, viewSettings } = useFlowStore(); - const { setMermaidDiagnostics, clearMermaidDiagnostics } = useMermaidDiagnosticsActions(); - const { addToast } = useToast(); - const textareaRef = useRef(null); - const { - code, - error, - diagnostics, - isApplying, - draftPreview, - hasDraftChanges, - liveSync, - setLiveSync, - handleCodeChange, - handleApply, - handleReset, - handleModeSelect, - } = useStudioCodePanelController({ - nodes, - edges, - mode, - onApply, - onModeChange, - activeTabId, - updateTab, - architectureStrictMode: viewSettings.architectureStrictMode, - setMermaidDiagnostics, - clearMermaidDiagnostics, - addToast, - t, - }); + activeTabId, + updateTab, + architectureStrictMode: viewSettings.architectureStrictMode, + setMermaidDiagnostics, + clearMermaidDiagnostics, + addToast, + t, + }); - const handleKeyDown = (event: React.KeyboardEvent) => { - if (['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) { - event.stopPropagation(); - } - if ((event.metaKey || event.ctrlKey) && ['a', 'c', 'v', 'x', 'z', 'y'].includes(event.key.toLowerCase())) { - event.stopPropagation(); - } - }; + const handleKeyDown = (event: React.KeyboardEvent) => { + if ( + ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key) + ) { + event.stopPropagation(); + } + if ( + (event.metaKey || event.ctrlKey) && + ['a', 'c', 'v', 'x', 'z', 'y'].includes(event.key.toLowerCase()) + ) { + event.stopPropagation(); + } + }; - const canApplyChanges = draftPreview.state === 'ready' && hasDraftChanges && !isApplying; - const applyButtonClassName = `h-8 ${mode === 'mermaid' ? 'flex-1' : 'min-w-[148px]'} justify-center px-3 py-1.5 text-xs ${canApplyChanges ? `border-transparent bg-[var(--brand-primary)] text-white hover:bg-[var(--brand-primary-600)] ${IS_BEVELED ? 'btn-beveled' : ''}` : ''}`; - const livePreviewTitle = liveSync - ? 'Live preview is on and auto-applies valid Mermaid changes.' - : 'Enable live preview for Mermaid changes.'; - const draftPreviewDetail = draftPreview.state === 'error' - ? friendlyDslError(draftPreview.detail) - : draftPreview.detail; + const canApplyChanges = draftPreview.state === 'ready' && hasDraftChanges && !isApplying; + const applyButtonClassName = `h-8 ${mode === 'mermaid' ? 'flex-1' : 'min-w-[148px]'} justify-center px-3 py-1.5 text-xs ${canApplyChanges ? `border-transparent bg-[var(--brand-primary)] text-white hover:bg-[var(--brand-primary-600)] ${IS_BEVELED ? 'btn-beveled' : ''}` : ''}`; + const livePreviewTitle = liveSync + ? 'Live preview is on and auto-applies valid Mermaid changes.' + : 'Enable live preview for Mermaid changes.'; + const draftPreviewDetail = + draftPreview.state === 'error' ? friendlyDslError(draftPreview.detail) : draftPreview.detail; - return ( -
-
-
-
- {MODE_OPTIONS.map(({ id, label }) => ( - - ))} -
- {mode === 'mermaid' ? ( - - ) : ( - - - - )} -
+ return ( +
+
+
+
+ {MODE_OPTIONS.map(({ id, label }) => ( + + ))} +
+ {mode === 'mermaid' ? ( +
+
+ ) : ( + + + + )} +
+
-
-
-