|
Documentation
Réserver une démoPlateforme
PlateformeMCPCLIAPI
Workflows
GuidesChangelog

Bienvenue

  • Vue d'ensemble
  • Authentification
  • Erreurs et codes d’état
  • Signatures de webhook

Localisation

  • Vue d'ensemble
  • Créer des jobs
  • Verrouiller les clés non traduisibles
  • Suivre un groupe de jobs
  • Récupérer un job
  • Lister les jobs
  • Envoi des webhooks
  • Progression en direct (WebSocket)

Pipeline

  • Vue d'ensemble
  • Pré-édition IA avant localisation
  • Relecture humaine
  • évaluation IA (post-édition)
  • Retravailler la traduction pour un rendu naturel
  • Vérification par rétrotraduction
  • Configurer le pipeline
  • Observer les exécutions du pipeline

Provisioning

  • Vue d'ensemble
  • Créer une tâche de provisionnement
  • Types de sources
  • Ce que l'IA extrait
  • Envoi des webhooks
  • Suivi en direct (WebSocket)

Synchrone

  • Localize
  • Recognize

Gestion du moteur

  • Engine Suggestions

Progression en direct via WebSocket

Vous avez créé un groupe de tâches. Quelque part, un utilisateur regarde un spinner, et « traduction vers 14 langues… » est techniquement vrai, mais totalement inutile — rien ne bouge. Ce que vous voulez, c’est voir le compteur grimper sous ses yeux : 3 prêtes, puis 4, puis une langue en échec, puis terminé.

Interroger le groupe de tâches vous y amène, mais c’est verbeux, et chaque requête vous renvoie un nouvel instantané qu’il faut comparer au précédent pour comprendre ce qui a vraiment changé. Le WebSocket renverse cette logique. Une seule connexion, puis le serveur pousse un événement chaque fois qu’une langue est résolue — et chaque message contient l’état complet du groupe, donc vous affichez l’instantané, sans jamais réconcilier de delta. Une trame perdue, une reconnexion, un onglet relancé : le message suivant vous redonne toute la vérité.

text
GET /jobs/localization/groups/:groupId/ws

Vous débutez avec la localisation asynchrone ? Commencez par la Vue d'ensemble. Le groupId ici est celui que vous avez reçu lorsque vous avez créé les tâches.

Sur cette page

  • Types de messages
  • Charges utiles des messages
  • L’intégrer à votre interface
  • Conservez votre clé API côté serveur

Types de messages#

Quatre types de messages transitent par le socket. Chacun vous indique ce qui vient de se produire tout en vous fournissant l’état actuel de l’ensemble du groupe.

TypeQuandChamps clés
snapshotÀ la connexion initialeÉtat complet du groupe
job.completedUne langue se termine avec succèsjobId, locale, plus l’état complet du groupe
job.failedUne langue échouejobId, locale, error, plus l’état complet du groupe
group.completedToutes les tâches sont résoluesgroupId, status, plus l’état complet du groupe. Le serveur ferme la connexion après ce message.

Chaque message contient un objet snapshot avec l’état actuel du groupe : totalJobs, completedJobs, completedWithWarningsJobs, failedJobs, ainsi qu’une map jobs indexée par ID de tâche, chacune avec son locale et son status. Ces compteurs sont les mêmes que ceux renvoyés par le point de terminaison du groupe de tâches — un instantané venant du socket et un poll du point de terminaison REST s’accordent donc sur l’avancement du groupe.

affichez l’instantané, sans jamais réconcilier

Vous n’avez jamais besoin de suivre les événements déjà vus, de rejouer les messages manqués ni de fusionner une mise à jour partielle dans l’état local. Lisez snapshot à chaque message et affichez votre interface à partir de là. Une reconnexion renvoie d’abord snapshot, de sorte qu’un client qui vient d’arriver et un client à l’écoute depuis le début convergent vers le même état.

Charges utiles des messages#

Voici les trames exactes envoyées par le serveur. Les identifiants ont leur format réel (ljg_ pour le groupe, ljb_ pour chaque tâche) ; le snapshot est abrégé avec "..." uniquement lorsqu’il répète une structure déjà montrée.

À la connexion, le serveur envoie l’état actuel :

json
{
  "type": "snapshot",
  "snapshot": {
    "groupId": "ljg_A1b2C3d4E5f6G7h8",
    "totalJobs": 3,
    "completedJobs": 1,
    "completedWithWarningsJobs": 0,
    "failedJobs": 0,
    "jobs": {
      "ljb_A1b2C3d4E5f6G7h8": { "locale": "de", "status": "completed" },
      "ljb_B2c3D4e5F6g7H8i9": { "locale": "fr", "status": "processing" },
      "ljb_C3d4E5f6G7h8I9j0": { "locale": "ja", "status": "queued" }
    }
  }
}

À mesure que chaque langue se termine, l’événement précise la langue concernée et inclut l’instantané mis à jour :

json
{
  "type": "job.completed",
  "jobId": "ljb_B2c3D4e5F6g7H8i9",
  "locale": "fr",
  "snapshot": {
    "groupId": "ljg_A1b2C3d4E5f6G7h8",
    "totalJobs": 3,
    "completedJobs": 2,
    "completedWithWarningsJobs": 0,
    "failedJobs": 0,
    "jobs": {
      "ljb_A1b2C3d4E5f6G7h8": { "locale": "de", "status": "completed" },
      "ljb_B2c3D4e5F6g7H8i9": { "locale": "fr", "status": "completed" },
      "ljb_C3d4E5f6G7h8I9j0": { "locale": "ja", "status": "processing" }
    }
  }
}

Un échec est un message normal, pas une connexion interrompue. job.failed contient la langue et un error, ainsi que le même instantané complet — la langue en échec affiche status: "failed" dans la map jobs, toutes les autres langues continuent d’arriver, et le socket continue jusqu’à group.completed :

json
{
  "type": "job.failed",
  "jobId": "ljb_C3d4E5f6G7h8I9j0",
  "locale": "ja",
  "error": "Model timeout after 30 seconds",
  "snapshot": { "...": "..." }
}

Lorsque toutes les tâches sont résolues, le serveur envoie un événement final et ferme la connexion :

json
{
  "type": "group.completed",
  "groupId": "ljg_A1b2C3d4E5f6G7h8",
  "status": "completed",
  "snapshot": { "...": "..." }
}

Le status final vaut completed lorsque chaque langue a réussi, completed_with_warnings lorsque chaque langue a produit une sortie mais qu’une ou plusieurs étapes facultatives du pipeline ont échoué pour au moins l’une d’entre elles, partial lorsque certaines langues ont réussi et d’autres ont échoué, et failed lorsqu’elles ont toutes échoué. Pour savoir ce que chacun de ces états signifie pour le groupe dans son ensemble, voir Suivre un groupe de tâches.

Affichez à partir de l’instantané dès que quelque chose vous échappe

Traitez les types de messages que vous connaissez, puis, pour tout ce que vous ne reconnaissez pas, retombez sur un rendu à partir de snapshot. Chaque message contient un instantané complet, donc un client qui choisit par défaut de l’afficher reste correct même face à une trame pour laquelle il n’a pas de branche spécifique.

L’intégrer à votre interface#

Le groupe est votre modèle de progression. Quand vous avez créé les tâches, la réponse 202 vous a renvoyé un groupId et un tableau jobs — une entrée par langue. Initialisez votre suivi de progression à partir de cette réponse, et vous obtenez la structure que le socket viendra remplir : le total à atteindre et un compteur qui démarre à zéro.

javascript
const { groupId, jobs } = await response.json();

await db.translationProgress.create({
  contentId: content.id,
  groupId,
  totalLanguages: jobs.length,
  completedLanguages: 0,
});

Ouvrez ensuite le socket sur ce groupId, puis à chaque message, lisez snapshot et réaffichez. Regardez le compteur grimper à mesure que les langues aboutissent, puis arrêtez-vous quand group.completed arrive :

javascript
import WebSocket from "ws";

const groupId = "ljg_A1b2C3d4E5f6G7h8";
const ws = new WebSocket(
  `wss://api.lingo.dev/jobs/localization/groups/${groupId}/ws`,
  { headers: { "X-API-Key": process.env.LINGO_API_KEY } }
);

ws.on("message", (raw) => {
  const event = JSON.parse(raw);
  const { snapshot } = event;

  switch (event.type) {
    case "snapshot":
      console.log(`${snapshot.completedJobs}/${snapshot.totalJobs} complete`);
      break;
    case "job.completed":
      console.log(`${event.locale} ready (${snapshot.completedJobs}/${snapshot.totalJobs})`);
      break;
    case "job.failed":
      console.error(`${event.locale} failed: ${event.error}`);
      break;
    case "group.completed":
      console.log(`All translations done: ${event.status}`);
      ws.close();
      break;
  }
});

Avec un groupe de trois langues, cela affiche l’exécution en temps réel :

text
1/3 complete
fr ready (2/3)
ja failed: Model timeout after 30 seconds
All translations done: partial

Le compteur a progressé tout seul, une langue a échoué sans faire tomber le flux, et partial vous a indiqué où l’exécution s’est arrêtée — exactement ce qu’il faut pour transformer votre spinner en une vraie barre de progression. À noter : la boucle n’accumule jamais d’état. Chaque branche lit le snapshot du message en cours, donc le même code reste correct à la première connexion, à chaque mise à jour comme après reconnexion.

Conservez votre clé API côté serveur#

Le socket s’authentifie avec votre clé API, la même clé à portée organisation que celle utilisée par les points de terminaison REST. Le navigateur n’est donc pas le bon endroit pour l’ouvrir — une clé API exposée dans le JavaScript client donne accès à chaque moteur de votre organisation à quiconque affiche le code source.

Connectez-vous depuis votre backend, pas depuis le navigateur

Ouvrez le WebSocket depuis votre serveur, là où la clé se trouve déjà, puis rediffusez les événements vers le navigateur via votre propre canal — un WebSocket ou un flux d’événements envoyés par le serveur que vous contrôlez. Votre frontend reçoit la progression en direct ; votre clé ne quitte jamais votre infrastructure.

C’est le même modèle que pour les webhooks : la connexion qui touche Lingo.dev est côté serveur, et ce qui parvient à l’utilisateur dépend de ce que votre application choisit de relayer.

Où cela s’intègre#

Le WebSocket est la vue en direct — il est lié à un seul groupe et se ferme lorsque ce groupe est terminé. Pour une transmission durable de serveur à serveur qui résiste à la fermeture d’un onglet ou à un déploiement, associez-le à des webhooks : le socket alimente l’interface tant que l’exécution est à l’écran, tandis que le webhook enregistre chaque résultat dès qu’il arrive. Déclenchez les deux depuis le même appel de création et vos utilisateurs voient la progression au moment où elle se produit, pendant que votre backend conserve la sortie, qu’il y ait quelqu’un pour la regarder ou non.

Livraison par webhook
Transmission durable de serveur à serveur de chaque langue au moment où elle se termine
Créer des tâches
Soumettez du contenu à traduire et obtenez le groupId auquel vous connecter ici
Suivre un groupe de tâches
États du groupe et signification d’une complétion partielle à l’échelle du groupe

Cette page vous a-t-elle été utile ?

Max PrilutskiyMax Prilutskiy·Mis à jour il y a environ 2 mois·6 min de lecture