Il y a 3 mois, je n’avais aucune connaissance en programmation d’applications. Je suis en Espagne depuis 8 mois et je suis venu avec une idée en tête. Avec le soutien de Gemini AI d’Antigravity, j’ai commencé à concrétiser mon idée d’une application de traduction de langues pour communiquer avec des amis d’Allemagne. Mon flux est composé de 4 nœuds (Webhook1 + HTTP REQUEST + JavaScript + Respond to Webhook). Quand j’appuie sur exécuter le flux de travail, il s’exécute en moins de 3 secondes, mais mon application qui est encore incomplète et qui est actuellement en version Web, qui s’active à partir d’un fichier index situé localement sur le bureau de mon ordinateur, n’arrive pas à effectuer la traduction vers la langue cible et finit par me retourner le message original à chaque fois. Je ne sais plus quoi faire.
Votre workflow s’exécutant en moins de 3 secondes signifie que l’automatisation fonctionne, mais cela ne prouve pas que la sortie de traduction est transmise correctement. Le problème n’est probablement pas la « traduction » elle-même ; il s’agit probablement d’un problème de mappage de données entre votre page web, le webhook, la requête HTTP, le nœud JavaScript et la réponse finale.
Je déboguerais nœud par nœud :
-
Vérifiez la sortie du nœud Webhook. Confirmez qu’il reçoit à la fois le texte original et la langue cible.
-
Vérifiez l’entrée du nœud HTTP Request. Confirmez qu’il envoie le texte et la langue cible corrects à l’API de traduction.
-
Vérifiez la sortie du nœud HTTP Request. Confirmez que l’API retourne réellement du texte traduit.
-
Vérifiez le nœud JavaScript. Il se peut qu’il extraie le mauvais champ JSON ou qu’il revienne au message original.
-
Vérifiez le nœud Respond to Webhook. Confirmez qu’il retourne
translatedText, pas le texte original. -
Vérifiez le JavaScript frontend. Confirmez qu’il affiche le champ traduit de la réponse webhook.
Comme votre app retourne toujours le texte original, je soupçonne qu’il y a une logique de secours comme translatedText || originalText, ou que le nœud de réponse/frontend affiche la variable de texte original. Supprimez le secours lors du débogage pour que le workflow échoue clairement si aucune traduction n’est trouvée.
La traduction elle-même devrait être simple. Nous avons déjà construit un pipeline de style transcription, et traduire du texte de transcription est généralement juste une autre étape de traitement. La partie la plus difficile est de s’assurer que la bonne variable se déplace dans la chaîne. Si vous partagez la sortie Webhook, la sortie HTTP Request, le code du nœud JavaScript et le code fetch frontend, nous pouvons probablement identifier le point de rupture exact.
C’est assez impressionnant de passer de zéro connaissance en programmation à un pipeline webhook fonctionnel, donc vous ne devriez pas abandonner, vous êtes plus proche que vous ne le pensez.
La réponse ci-dessus couvre bien toutes les étapes de débogage, mais il y a une chose importante à ajouter : la cause la plus courante du message « retourne le message original » dans cette configuration est que le nœud JavaScript récupère le mauvais champ de la réponse de l’API.
Vous devriez essayer d’ajouter un console.log ou d’utiliser l’aperçu de sortie intégré de n8n pour voir exactement ce que le nœud HTTP Request retourne. Essayez de regarder spécifiquement la structure JSON. Le texte traduit est généralement imbriqué un niveau plus profond que prévu, quelque chose comme response.data.translations[0].translatedText selon l’API que vous utilisez.
Si vous partagez quelle API de traduction vous utilisez et collez le code JavaScript qui a été utilisé, quelqu’un pourra probablement identifier le problème en 2 minutes.
« Merci beaucoup @pratham_gupta et @AnthonyAtXRay de prendre le temps de répondre ! Vos points de débogage sont excellents.
Pour vous donner un peu plus de contexte : au début, quand j’ai fait les tests initiaux, tout le flux semblait répondre correctement. Cependant, les vrais problèmes dans le navigateur ont commencé à se manifester plus fortement récemment. Après une analyse approfondie, nous soupçonnons que la logique interne de n8n fonctionne bien, mais l’échec se produit dans la communication finale : j’exécute l’application web localement en ouvrant le fichier index.html directement depuis mon ordinateur (file://). Tout indique que Google Chrome ou les politiques réseau locales bloquent par CORS la réponse qui provient de l’adresse IP de n8n.
De plus, pour couronner le tout, mes crédits prépayés de l’API Google viennent de s’épuiser, alors le flux est resté en pause.
Pour valider si le mappage des variables est aussi fin que vous le suggérez, je vous partage ci-dessous la structure de mon nœud JavaScript et le flux général (sans identifiants). Pensez-vous que ma théorie selon laquelle le format file:// et CORS sont responsables du blocage dans le navigateur a du sens, ou voyez-vous une erreur de logique dans les variables ? »
{
“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”: “Répondre au 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=VOTRE_CLÉ_API_ICI”,
“sendBody”: true,
“specifyBody”: “json”,
“jsonBody”: “={{ { “contents”: [{ “parts”: [{ “text”: $json.body.text + " - Traduire ceci en " + $json.body.target_lang }] }] } }}”,
“options”: {}
},
“id”: “06da87ea-d639-41fa-a859-50ae26c35224”,
“name”: “Requête 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”: “Code en JavaScript”,
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
528,
112
]
}
],
“connections”: {
“Webhook1”: {
“main”: [
[
{
“node”: “Requête HTTP”,
“type”: “main”,
“index”: 0
}
]
]
},
“Requête HTTP”: {
“main”: [
[
{
“node”: “Code en JavaScript”,
“type”: “main”,
“index”: 0
}
]
]
},
“Code en JavaScript”: {
“main”: [
[
{
“node”: “Répondre au Webhook”,
“type”: “main”,
“index”: 0
}
]
]
}
],
“pinData”: {},
“meta”: {
“templateCredsSetupCompleted”: true,
“instanceId”: “ANONYMOUS_INSTANCE_ID”
}
}
Freddy, les captures d’écran seraient utiles, mais sur la base de ce que vous avez décrit, je réduirais cela à une seule question spécifique :
À quel moment le texte traduit disparaît-il ?
Votre workflow n8n fonctionne peut-être correctement, mais l’application web lit peut-être quand même le mauvais champ.
Je testerais dans cet ordre :
- Nœud Webhook
Confirmez que les données entrantes contiennent quelque chose comme :
{
"text": "hello",
"targetLanguage": "German"
}
- Nœud HTTP Request
Ouvrez la sortie d’exécution du nœud et vérifiez si l’API de traduction renvoie le texte traduit.
Par exemple, quelque chose comme :
{
"translatedText": "Hallo"
}
ou parfois elle peut être imbriquée plus profondément, comme :
{
"data": {
"translation": "Hallo"
}
}
- Nœud JavaScript
C’est un point de rupture courant. Le code peut lire le mauvais champ.
Pour déboguer, ne retournez pas le message d’origine comme solution de secours. Retournez plutôt une erreur évidente :
const output = $json.translatedText;
if (!output) {
throw new Error("No translated text found. Check HTTP Request output field name.");
}
return [
{
json: {
translatedText: output
}
}
];
Si le texte traduit est imbriqué, vous devez ajuster le chemin d’accès au champ en fonction de la sortie réelle du nœud HTTP Request.
- Nœud Respond to Webhook
Assurez-vous qu’il retourne la valeur traduite, pas l’entrée d’origine.
Exemple de réponse :
{
"translatedText": "={{$json.translatedText}}"
}
- Code de récupération frontale
Votre page web locale fait peut-être quelque chose comme ceci :
resultBox.innerText = data.text;
alors qu’elle devrait faire :
resultBox.innerText = data.translatedText;
Comme votre application renvoie toujours le message d’origine, ma meilleure hypothèse est l’une de celles-ci :
-
le nœud JavaScript revient au texte d’origine
-
le nœud Respond to Webhook est mappé au champ d’origine
-
le frontale affiche le champ d’origine au lieu du champ traduit
-
le nœud HTTP Request renvoie la traduction dans un chemin JSON imbriqué, mais le nœud JS lit le mauvais chemin
Meilleur moyen de déboguer : retournez temporairement la sortie complète du nœud HTTP Request directement depuis Respond to Webhook. Ensuite, testez depuis l’application web et vérifiez ce que votre navigateur reçoit réellement. Une fois que vous voyez la structure JSON réelle, mapper le champ traduit devrait être facile.
Votre théorie sur CORS est exactement correcte, le JSON de votre workflow expose le problème spécifique.
Votre nœud Webhook a « allowedOrigins » défini sur « asterisk » (astérisque), ce qui est correct. Mais votre nœud Respond to Webhook a « Access-Control-Allow-Origin » défini sur une chaîne vide. Il faudra le changer en « asterisk » (astérisque) également, sinon Chrome bloquera la réponse même si la requête passe.
Le problème suivant concerne le protocole file:// lui-même. Chrome finit par bloquer les requêtes fetch depuis des pages file:// vers des URL externes, indépendamment des en-têtes CORS. C’est une correction simple : au lieu d’ouvrir index.html directement, vous le servez depuis un serveur local.
Si vous avez Python d’installé : python -m http.server 8080 dans le dossier contenant votre index.html, puis ouvrez http://localhost:8080
En ce qui concerne les crédits de l’API Google, une fois que vous les aurez épuisés, la logique du nœud JavaScript elle-même semble correcte. Et le mappage des variables vers candidates[0].content.parts[0].text est le bon chemin pour les réponses de Gemini.