我需要幫助,我算是初學者

3個月前,我對應用程序編程一無所知,在西班牙待了8個月,我帶著一個想法來到這裡。在來自Antigravity的Gemini AI的支持下,我開始將我關於翻譯語言應用的想法付諸實踐,以便與我在德國的朋友交流。我的流程由4個節點組成(Webhook1+HTTP REQUEST+JavaScript+Respond to Webhook),當我點擊執行工作流時,它在不到3秒內執行,但我的應用程序仍未完成,目前是網頁版本,它從本地存放在我電腦桌面的index文件激活,但它無法完成目標語言的翻譯,最終總是給我返回原始消息;我已經不知道該怎麼辦了

1 個讚

您的工作流在 3 秒內完成執行意味著自動化正在執行,但這並不能證明翻譯輸出已正確傳遞。問題可能不在「翻譯」本身;而很可能是您網頁、webhook、HTTP 請求、JavaScript 節點和最終回應之間的資料對應問題。

我會逐個節點進行偵錯:

  1. 檢查 Webhook 節點的輸出。確認它接收了原始文本和目標語言。

  2. 檢查 HTTP Request 節點的輸入。確認它將正確的文本和目標語言傳送到翻譯 API。

  3. 檢查 HTTP Request 節點的輸出。確認 API 實際返回翻譯後的文本。

  4. 檢查 JavaScript 節點。它可能在提取錯誤的 JSON 欄位,或者回退到原始訊息。

  5. 檢查 Respond to Webhook 節點。確認它返回的是 translatedText,而不是原始文本。

  6. 檢查前端 JavaScript。確認它顯示的是 webhook 回應中的翻譯欄位。

由於您的應用始終返回原始文本,我懷疑存在類似 translatedText || originalText 的回退邏輯,或者回應節點/前端正在顯示原始文本變數。在偵錯時移除回退邏輯,這樣當找不到翻譯時工作流會明確失敗。

翻譯本身應該很簡單。我們已經建立了一個轉錄風格的管線,翻譯文字記錄通常只是另一個處理步驟。更困難的部分是確保正確的變數在整個鏈中移動。如果您分享 Webhook 輸出、HTTP Request 輸出、JavaScript 節點程式碼和前端 fetch 程式碼,我們可能能夠識別確切的中斷點。

2 個讚

從零開始的程式設計知識到建立一個可運作的 webhook 管道是相當令人印象深刻的,所以你不應該放棄,你比你想的更接近成功。

上面的回覆涵蓋了所有的除錯步驟,不過有一件值得補充的事:在這個設置中,「返回原始訊息」最常見的原因是 JavaScript 節點從 API 回應中抓取了錯誤的欄位。

你應該嘗試添加一個 console.log 或使用 n8n 內建的輸出預覽來看看 HTTP Request 節點確實返回了什麼。試著特別查看 JSON 結構。翻譯後的文字通常被嵌套得比預期的更深一層,所以可能會是像 response.data.translations[0].translatedText 這樣的結構,取決於你使用的是哪個 API。

如果你分享你正在呼叫的翻譯 API 是哪個,並貼上使用的 JavaScript 程式碼,有人可能在 2 分鐘內就能找到問題所在。

2 個讚

「非常感謝 @pratham_gupta@AnthonyAtXRay 抽空回覆!你們的除錯要點都非常出色。

為了給你們多一些背景資訊:一開始當我進行初步測試時,整個流程似乎反應良好。不過,瀏覽器中的實際問題最近才開始更明顯地浮現。經過深入分析後,我們懷疑 n8n 的內部邏輯是正常的,但故障發生在最後的通訊階段:我正在以本機方式執行網頁應用程式,直接從我的電腦開啟 index.html 檔案(file://)。一切跡象都指向 Google Chrome 或本機網路政策正在透過 CORS 封鎖來自 n8n IP 位址的回應。

而且,更糟的是,我的 Google API 預付額度剛好用完了,所以流程被暫停了。

為了驗證變數對應是否如你們所建議的那樣精細,我在下方分享我的 JavaScript 節點結構和一般流程(不含認證資訊)。你們認為我的理論——file:// 格式和 CORS 是導致瀏覽器封鎖的罪魁禍首——是否有理?或者你們發現變數邏輯中有什麼錯誤嗎?」

2 個讚

{
“nodes”: [
{
“parameters”: {
“respondWith”: “json”,
“responseBody”: “={{ $json }}”,
“options”: {
“responseCode”: 200,
“responseHeaders”: {
“entries”: [
{
“name”: “Content-Type”,
“value”: “application/json”
},
{
“name”: “Access-Control-Allow-Origin”,
“value”: “"
},
{
“name”: “Access-Control-Allow-Headers”,
“value”: "

}
]
}
}
},
“type”: “n8n-nodes-base.respondToWebhook”,
“typeVersion”: 1.5,
“position”: [
752,
112
],
“id”: “7eb0364c-e218-47a7-ba7e-f9d8fe8bb8f8”,
“name”: “回應 Webhook”
},
{
“parameters”: {
“httpMethod”: “POST”,
“path”: “98bd0d2c-fcf4-49b7-b501-72c81c5d9d44”,
“responseMode”: “responseNode”,
“options”: {
“allowedOrigins”: “*”
}
},
“type”: “n8n-nodes-base.webhook”,
“typeVersion”: 2.1,
“position”: [
80,
112
],
“id”: “0af6f18b-0e1a-4d5c-bca6-7573f4a31cb9”,
“name”: “Webhook1”,
“webhookId”: “c1603781-563f-4655-9b6d-1170e847c6f0”
},
{
“parameters”: {
“method”: “POST”,
“url”: “https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key=TU_API_KEY_AQUÍ”,
“sendBody”: true,
“specifyBody”: “json”,
“jsonBody”: “={{ { “contents”: [{ “parts”: [{ “text”: $json.body.text + " - 將此翻譯為 " + $json.body.target_lang }] }] } }}”,
“options”: {}
},
“id”: “06da87ea-d639-41fa-a859-50ae26c35224”,
“name”: “HTTP 請求”,
“type”: “n8n-nodes-base.httpRequest”,
“typeVersion”: 4.4,
“position”: [
304,
112
]
},
{
“parameters”: {
“jsCode”: “const geminiResponse = $input.first().json;\nconst translatedText = geminiResponse.candidates[0].content.parts[0].text.trim();\n\nreturn [\n {\n json: {\n status: “success”,\n original_text: $(‘Webhook1’).item.json.body.text,\n translated_text: translatedText,\n audio_base64: “”\n }\n }\n];”
},
“id”: “576fa8a4-896f-4d33-ad1a-8cfe5d204ec8”,
“name”: “JavaScript 程式碼”,
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
528,
112
]
}
],
“connections”: {
“Webhook1”: {
“main”: [
[
{
“node”: “HTTP 請求”,
“type”: “main”,
“index”: 0
}
]
]
},
“HTTP 請求”: {
“main”: [
[
{
“node”: “JavaScript 程式碼”,
“type”: “main”,
“index”: 0
}
]
]
},
“JavaScript 程式碼”: {
“main”: [
[
{
“node”: “回應 Webhook”,
“type”: “main”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateCredsSetupCompleted”: true,
“instanceId”: “ANONYMOUS_INSTANCE_ID”
}
}

1 個讚

Freddy,截圖會有幫助,但根據你的描述,我會把問題縮小到一個具體的問題:

翻譯後的文字在哪個環節消失了?

你的 n8n 工作流程可能運行正常,但網頁應用程式可能仍在讀取錯誤的欄位。

我會按這個順序進行測試:

  1. Webhook 節點
    確認傳入的資料包含類似這樣的內容:
{
  "text": "hello",
  "targetLanguage": "German"
}

  1. HTTP Request 節點
    開啟節點執行輸出,檢查翻譯 API 是否回傳了翻譯後的文字。
    例如,類似這樣:
{
  "translatedText": "Hallo"
}

或有時可能會更深層地嵌套,像這樣:

{
  "data": {
    "translation": "Hallo"
  }
}

  1. JavaScript 節點
    這是常見的中斷點。程式碼可能在讀取錯誤的欄位。

為了除錯,不要將原始訊息作為備用方案回傳。改為回傳一個明顯的錯誤:

const output = $json.translatedText;

if (!output) {
  throw new Error("No translated text found. Check HTTP Request output field name.");
}

return [
  {
    json: {
      translatedText: output
    }
  }
];

如果翻譯後的文字是嵌套的,你需要根據實際的 HTTP Request 輸出來調整欄位路徑。

  1. Respond to Webhook 節點
    確保它回傳的是翻譯後的值,而不是原始輸入。

回應範例:

{
  "translatedText": "={{$json.translatedText}}"
}

  1. 前端提取程式碼
    你的本地網頁可能在做這樣的事:
resultBox.innerText = data.text;

但實際上應該是:

resultBox.innerText = data.translatedText;

因為你的應用程式總是回傳原始訊息,我最有把握的猜測是以下其中一個:

  • JavaScript 節點回退到了原始文字

  • Respond to Webhook 節點對應到了原始欄位

  • 前端顯示的是原始欄位而不是翻譯後的欄位

  • HTTP Request 節點以嵌套的 JSON 路徑回傳翻譯,但 JS 節點讀取的是錯誤的路徑

最佳除錯做法:暫時直接從 Respond to Webhook 回傳完整的 HTTP Request 輸出。然後從網頁應用程式測試,檢查你的瀏覽器實際收到了什麼。一旦你看到真實的 JSON 結構,對應翻譯後的欄位應該就很容易了。

1 個讚

你對CORS的理論完全正確,你的工作流JSON暴露了具體的問題。

你的Webhook節點的「allowedOrigins」設定為「asterisk」,這是應該的。但是你的「Respond to Webhook」節點的「Access-Control-Allow-Origin」設定為空字符串。這需要改為「asterisk」,否則即使請求通過,Chrome也會阻止回應。

下一個問題是file://協議本身。Chrome最終會阻止從file://頁面到外部URL的fetch請求,不管CORS標頭如何。修復很簡單——不要直接開啟index.html,改為從本地伺服器提供。

如果你已安裝Python:在包含index.html的資料夾中執行python -m http.server 8080,然後開啟http://localhost:8080

至於Google API額度,填完後,JavaScript節點邏輯本身看起來是正確的。而且變數映射到candidates[0].content.parts[0].text是Gemini回應的正確路徑。