{
  "id": "rqGKUYvnfoH0j2f9JONYn",
  "name": "Multi-Language Content Translation Pipeline with AI Quality Control",
  "tags": [],
  "nodes": [
    {
      "id": "91a11e85-2fdd-4244-9475-c4be9c65b274",
      "name": "Main Overview1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        240
      ],
      "parameters": {
        "width": 512,
        "height": 492,
        "content": "## How it works\nThis workflow automates a professional-grade translation pipeline. It triggers via Webhook or Schedule, translates source content into multiple target languages using DeepL, and then passes the results to an AI Agent. The AI evaluates the translation for accuracy and cultural nuance. \n\nApproved content is automatically published as a draft to WordPress, while any translations falling below quality standards are flagged in Slack for manual review. Finally, all results are aggregated and logged into Google Sheets to build a translation memory.\n\n## Setup steps\n1. **Credentials:** Connect your DeepL, OpenAI, WordPress, Slack, and Google Sheets accounts.\n2. **Configuration:** In the 'Translation Configuration' node, define your source language and list of target languages (e.g., DE, FR, JA).\n3. **Google Sheets:** Create a spreadsheet with headers: contentId, title, sourceLanguage, targetLanguage, translatedText, and qualityScore.\n4. **Slack:** Select your notification channels in the 'Flag for Manual Review' and 'Send Completion Summary' nodes."
      },
      "typeVersion": 1
    },
    {
      "id": "076c7e6f-e211-43d0-8262-05d648db13c3",
      "name": "Section: Config1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 1040,
        "height": 380,
        "content": "## 1. Setup & Logic\nDefines translation parameters and splits the workflow to process multiple languages in parallel."
      },
      "typeVersion": 1
    },
    {
      "id": "99f5ccf1-ece2-49a1-ae85-24491628efca",
      "name": "Section: Translation1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 380,
        "content": "## 2. Translation\nConnects to DeepL API to perform the core translation task."
      },
      "typeVersion": 1
    },
    {
      "id": "83879bc8-6cc3-4184-aced-73abb32c89b4",
      "name": "Section: AI QA1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1456,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 460,
        "content": "## 3. AI Quality Guard\nAI Agent reviews the translation for accuracy, fluency, and tone before approval."
      },
      "typeVersion": 1
    },
    {
      "id": "3534279a-d051-47ca-a0ca-ad4e34df4f98",
      "name": "Section: Distribution1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2064,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 1340,
        "height": 460,
        "content": "## 4. Output & Logging\nPublishes approved content, flags issues in Slack, and saves all data to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "d913d16a-62dc-4675-8610-d40e6f5c268f",
      "name": "Content Webhook",
      "type": "n8n-nodes-base.webhook",
      "onError": "continueRegularOutput",
      "position": [
        -32,
        752
      ],
      "parameters": {
        "path": "translate-content",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "c43644db-b6e7-42b8-82ad-04f4b7f928c4",
      "name": "Scheduled Batch",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -32,
        912
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 4
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3c4d9377-5d86-4f8c-acfd-0ce7ebabf3bc",
      "name": "Merge Triggers",
      "type": "n8n-nodes-base.merge",
      "position": [
        176,
        832
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3
    },
    {
      "id": "994c9934-ae0f-4c0c-bdb1-3214be882b44",
      "name": "Translation Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        400,
        832
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "{\n  \"sourceLanguage\": \"EN\",\n  \"targetLanguages\": [\"DE\", \"FR\", \"ES\", \"JA\"],\n  \"contentType\": \"article\",\n  \"preserveFormatting\": true,\n  \"qualityThreshold\": 0.85,\n  \"distributionTargets\": [\"wordpress\", \"contentful\"]\n}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "48bfff0b-4cd5-4484-97ac-9f07d46d20b0",
      "name": "Prepare Source Content",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        832
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst config = $('Translation Configuration').first().json;\n\nconst sourceContent = item.json.content || item.json.text || 'Sample content for translation';\nconst title = item.json.title || 'Untitled';\nconst contentId = item.json.id || `content-${Date.now()}`;\n\nreturn [{\n  json: {\n    contentId: contentId,\n    title: title,\n    sourceText: sourceContent,\n    sourceLanguage: config.sourceLanguage,\n    targetLanguages: config.targetLanguages,\n    config: config,\n    createdAt: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c76875fa-4e70-4408-b760-9600c8b1c7d1",
      "name": "Split Target Languages",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        848,
        832
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "targetLanguages"
      },
      "typeVersion": 1
    },
    {
      "id": "f5aa15d4-2b12-4c86-8f89-8fa048f046d9",
      "name": "DeepL Translate",
      "type": "n8n-nodes-base.deepL",
      "position": [
        1088,
        832
      ],
      "parameters": {
        "text": "={{ $('Prepare Source Content').first().json.sourceText }}",
        "translateTo": "={{ $json }}",
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "41824a29-8c27-432c-9a0b-bf1e3191b58b",
      "name": "Format Translation Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        832
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst sourceData = $('Prepare Source Content').first().json;\nconst targetLang = $('Split Target Languages').item.json;\n\nconst translatedText = item.json.text || item.json.translations?.[0]?.text || '';\n\nreturn [{\n  json: {\n    contentId: sourceData.contentId,\n    title: sourceData.title,\n    sourceLanguage: sourceData.sourceLanguage,\n    targetLanguage: targetLang,\n    sourceText: sourceData.sourceText,\n    translatedText: translatedText,\n    characterCount: translatedText.length,\n    translatedAt: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "356b6442-0592-4683-8eef-785b1c162f50",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1568,
        1024
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {
          "temperature": 0.2
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6327bd2d-0984-4cac-b61a-6b78aa3822df",
      "name": "AI Quality Reviewer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1520,
        832
      ],
      "parameters": {
        "text": "=Review this translation for quality:\n\nSource Language: {{ $json.sourceLanguage }}\nTarget Language: {{ $json.targetLanguage }}\n\nOriginal Text:\n{{ $json.sourceText.substring(0, 500) }}\n\nTranslated Text:\n{{ $json.translatedText.substring(0, 500) }}\n\nEvaluate and respond in this exact JSON format:\n{\n  \"qualityScore\": 0.0 to 1.0,\n  \"accuracyScore\": 0.0 to 1.0,\n  \"fluencyScore\": 0.0 to 1.0,\n  \"issues\": [\"list any issues found\"],\n  \"suggestions\": [\"improvement suggestions if any\"],\n  \"approved\": true/false (true if qualityScore >= 0.85),\n  \"summary\": \"brief quality assessment\"\n}",
        "options": {
          "systemMessage": "You are a professional translator and quality assurance specialist. Evaluate translations for accuracy, fluency, and cultural appropriateness. Be thorough but fair in your assessment."
        }
      },
      "typeVersion": 1.7
    },
    {
      "id": "7ea4a7f6-6530-4201-8f60-777a0c490fc6",
      "name": "Parse Quality Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1824,
        832
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst translationData = $('Format Translation Result').item.json;\n\nlet qualityResult;\ntry {\n  const responseText = item.json.output || item.json.text || '';\n  const jsonMatch = responseText.match(/\\{[\\s\\S]*\\}/);\n  qualityResult = jsonMatch ? JSON.parse(jsonMatch[0]) : {\n    qualityScore: 0.8,\n    accuracyScore: 0.8,\n    fluencyScore: 0.8,\n    issues: [],\n    suggestions: [],\n    approved: true,\n    summary: 'Default approval - manual review recommended'\n  };\n} catch (e) {\n  qualityResult = {\n    qualityScore: 0.7,\n    accuracyScore: 0.7,\n    fluencyScore: 0.7,\n    issues: ['Parse error'],\n    suggestions: ['Manual review required'],\n    approved: false,\n    summary: 'Quality check failed: ' + e.message\n  };\n}\n\nreturn [{\n  json: {\n    ...translationData,\n    quality: qualityResult,\n    isApproved: qualityResult.approved,\n    processedAt: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "63280c68-a36f-4562-b2c0-c98d9e1e7006",
      "name": "Quality Approved?",
      "type": "n8n-nodes-base.if",
      "position": [
        2096,
        832
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "approval-check",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.isApproved }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "7e7f7092-ca4c-4733-8136-2b1b1fab325a",
      "name": "Publish to WordPress",
      "type": "n8n-nodes-base.wordpress",
      "position": [
        2320,
        736
      ],
      "parameters": {
        "title": "={{ $json.title }} ({{ $json.targetLanguage }})",
        "additionalFields": {
          "status": "draft"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e220e028-6ab8-4f64-b2db-e723ba534a58",
      "name": "Flag for Manual Review",
      "type": "n8n-nodes-base.slack",
      "position": [
        2320,
        944
      ],
      "parameters": {
        "text": "=Translation needs review\n\n*Content:* {{ $json.title }}\n*Language:* {{ $json.sourceLanguage }} -> {{ $json.targetLanguage }}\n*Quality Score:* {{ $json.quality.qualityScore }}\n*Issues:* {{ $json.quality.issues.join(', ') || 'None specified' }}\n\nPlease review and approve manually.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#translation-review"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "83053f56-68ba-4d08-abd9-6fd6f9a2fef3",
      "name": "Aggregate All Translations",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2576,
        832
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "9d322c83-cd10-4c04-8e33-866b809d459a",
      "name": "Log to Translation Memory",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2784,
        832
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "d352f673-c128-4717-9252-9a983be605d2",
      "name": "Send Completion Summary",
      "type": "n8n-nodes-base.slack",
      "position": [
        2976,
        832
      ],
      "parameters": {
        "text": "=Translation batch complete!\n\n*Total Languages:* {{ $json.data.length }}\n*Approved:* {{ $json.data.filter(t => t.isApproved).length }}\n*Needs Review:* {{ $json.data.filter(t => !t.isApproved).length }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#content-updates"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "3b9eb21b-fd30-43cb-b1d7-593193409d86",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3184,
        832
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ {success: true, translationsProcessed: $json.data.length, approved: $json.data.filter(t => t.isApproved).length} }}"
      },
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "4076abbd-439c-4a81-890b-7efc1385d22c",
  "connections": {
    "Merge Triggers": {
      "main": [
        [
          {
            "node": "Translation Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Content Webhook": {
      "main": [
        [
          {
            "node": "Merge Triggers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeepL Translate": {
      "main": [
        [
          {
            "node": "Format Translation Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scheduled Batch": {
      "main": [
        [
          {
            "node": "Merge Triggers",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Quality Reviewer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Quality Approved?": {
      "main": [
        [
          {
            "node": "Publish to WordPress",
            "type": "main",
            "index": 0
          },
          {
            "node": "Flag for Manual Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Quality Reviewer": {
      "main": [
        [
          {
            "node": "Parse Quality Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Quality Result": {
      "main": [
        [
          {
            "node": "Quality Approved?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish to WordPress": {
      "main": [
        [
          {
            "node": "Aggregate All Translations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flag for Manual Review": {
      "main": [
        [
          {
            "node": "Aggregate All Translations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Source Content": {
      "main": [
        [
          {
            "node": "Split Target Languages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Target Languages": {
      "main": [
        [
          {
            "node": "DeepL Translate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Completion Summary": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Translation Result": {
      "main": [
        [
          {
            "node": "AI Quality Reviewer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Translation Memory": {
      "main": [
        [
          {
            "node": "Send Completion Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Translation Configuration": {
      "main": [
        [
          {
            "node": "Prepare Source Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate All Translations": {
      "main": [
        [
          {
            "node": "Log to Translation Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}