Docsbook
Aperçu

Traductions par IA

Une passe de traduction prend le Markdown déjà présent dans votre dépôt, le restitue exactement comme la page en ligne le restitue, le divise, traduit les parties lisibles par les humains et stocke le résultat pour chaque page et chaque langue. Il n’y a pas de fichiers de traduction, pas de clés de message ni d’étape d’exportation. Cette page décrit le mécanisme, au niveau de ce que fait réellement le code.

Ce qui déclenche une passe#

Cinq éléments, et chaque exécution enregistre lequel — afin que le panneau puisse indiquer Déclenché par le commit a1b2c3d plutôt que d'attribuer un push à votre compte.

Déclencheur Ce qui le provoque
language_enabled Vous avez activé une langue.
commit Le scanner du mode automatique a détecté que la tête du dépôt avait changé.
manual Vous avez appuyé sur Traduire maintenant, ou quelqu'un d'autre l'a fait depuis le tableau de bord.
agent Un agent appelé run_translation_pass. La clé et l'identifiant d'exécution de l'agent sont inscrits sur la ligne du travail.
Le lanceur de reprise Toutes les 2 minutes, une exécution cron récupère les exécutions dont le signal de présence est resté silencieux pendant 15 minutes, libère leurs verrous et relance jusqu'à trois travaux actifs restés inactifs pendant 90 secondes.

Le scanner ne vérifie qu'un espace de travail qu'il n'a pas examiné depuis 15 minutes, et seulement quatre espaces de travail par cycle, classés selon celui qui n'a pas été scanné depuis le plus longtemps. Il s'arrête immédiatement lorsque la tête du dépôt est inchangée — et le marqueur auquel il se compare n'avance que lorsque toutes les langues activées ont été trouvées synchronisées sur ce commit ; ainsi, une exécution interrompue faute de budget ne peut pas figer un espace de travail à une traduction partielle et empêcher définitivement toute nouvelle vérification.

Une passe ne démarre jamais plus de trois langues à la fois, en commençant par les plus prioritaires : chaque exécution représente plusieurs minutes de travail de modèle facturé, et une étape d'agent qui en ouvrirait dix consommerait le budget d'un mois sur un seul déclencheur. Les autres sont signalées comme over_language_cap et prises en charge la fois suivante, ce qui est la version honnête de « pas maintenant ».

Comment une page est segmentée#

L’unité de traduction n’est pas la page. C’est une section.

  1. Votre Markdown est prétraité et rendu via le même pipeline que celui utilisé par la page en ligne, y compris votre liste de blocage des widgets. La traduction voit donc la page telle qu’un lecteur la voit, et non une seconde interprétation de la source.
  2. Le HTML rendu est séparé aux limites <h2> et <h3>. Le contenu situé avant le premier titre devient son propre bloc initial.
  3. Un bloc de plus de 9 000 caractères est à nouveau séparé — mais uniquement aux limites des blocs de niveau supérieur (</p>, </li>, </table>, </pre>, </figure>, </h1></h6>), afin qu’un fragment ne soit jamais coupé au milieu d’une balise.
  4. Chaque bloc est haché à partir de son propre contenu. Le hachage et la langue constituent la clé du cache.
  5. Les blocs sont traduits au maximum 3 à la fois, chacun avec un délai d’expiration amont de 30 secondes, puis concaténés dans leur ordre initial.

Deux éléments découlent de cette conception, et c’est la raison même pour laquelle elle a été choisie :

  • Modifier un paragraphe entraîne la retraduction d’une section. Le hachage de tous les autres blocs reste inchangé, ils sont donc servis depuis le cache. Corriger une coquille coûte une section, pas une page. La répartition — le nombre de blocs réutilisés par rapport au nombre envoyé au modèle — est enregistrée une fois par page dans le registre des dépenses, de sorte que l’économie est une valeur mesurée plutôt qu’une simple affirmation.
  • La terminologie ne peut pas dériver dans un texte que vous n’avez pas modifié. Une section non modifiée est identique octet par octet à la dernière fois où elle a été traduite, car il s’agit littéralement de la même chaîne mise en cache.

Les requêtes sont envoyées avec une température de 0, et le budget de jetons de sortie est calculé à partir de la longueur de l’entrée plutôt que réservé de manière fixe — avec un multiplicateur de 2,6, choisi parce que le cyrillique et les caractères CJK nécessitent bien plus de jetons par caractère que la source anglaise, tandis qu’un budget de 1,5× produisait des pages tronquées.

Qu’est-ce qui est protégé du modèle#

Il existe ici deux types de protection différents, et les confondre est la raison pour laquelle la documentation finit par promettre plus que ce que le code fournit.

Protégé structurellement — le modèle ne le voit jamais#

Élément Mécanisme
Blocs de code délimités Extraits avant la requête et remplacés par __CODE_BLOCK_N__ ; restaurés octet par octet ensuite.
Code en ligne (`like this`) Même extraction, même restauration octet par octet.
Clés et valeurs des métadonnées frontmatter Ne parviennent jamais au modèle : la traduction s'exécute sur le HTML rendu, et les métadonnées frontmatter ont été utilisées lors du rendu.
Marqueurs de widget (<!-- widget:name -->) Ne parviennent pas non plus au modèle : les widgets sont développés en HTML par le pipeline de rendu avant le découpage en segments. Il ne reste aucun marqueur susceptible d'être altéré. Le texte visible à l'intérieur d'un widget — le titre d'une carte, par exemple — est de la prose et est traduit.

Ce sont des garanties. Un modèle ne peut pas modifier, réagencer ou « traduire » un exemple de code qui ne lui a jamais été fourni.

Protégés par instruction — vérifiez-les, ne les tenez pas pour acquis#

Le prompt indique au modèle, comme règles absolues, de ne pas traduire ni modifier les balises HTML, les attributs, les noms de classes, les identifiants, les valeurs href ou les attributs de données, de ne pas modifier la structure HTML, de ne pas traduire les identifiants de code ni les noms de variables, de ne pas ajouter de commentaire et de reproduire exactement les espaces réservés __CODE_BLOCK_N__. Il s’agit d’une instruction forte destinée à un modèle exécuté avec une température de 0, et elle est respectée en pratique — mais c’est une instruction, pas un mécanisme, et le terme honnête pour cela est généralement.

Trois conséquences qu’il est utile de connaître :

  • Les liens conservent leurs cibles. href est un attribut, et les attributs figurent sur la liste des éléments auxquels il ne faut pas toucher. Le texte du lien est de la prose et est traduit.
  • Les ancres des titres restent dans la langue source. Les attributs id du titre sont définis avant la traduction et il est demandé de ne pas les modifier, de sorte qu’un lien profond vers une ancre de titre en anglais continue de fonctionner sur la page traduite.
  • Le texte alt des images n’est pas traduit. Il s’agit d’un attribut HTML, et la règle qui protège href protège également alt. Si un texte alternatif accessible dans la langue du lecteur est important pour vous, il s’agit d’une lacune, pas d’une fonctionnalité.

Traduits par ensembles, pas un à la fois#

Les libellés de navigation sont traduits en un seul groupe dans une requête unique qui doit renvoyer le même nombre de libellés, dans le même ordre ; une réponse mal formée ou incohérente conserve les originaux plutôt que de faire des suppositions. Si chaque libellé renvoyé est identique à l’original — signe qu’aucune traduction n’a eu lieu — le résultat est supprimé plutôt que mis en cache, afin que la tentative suivante puisse recommencer au lieu de conserver définitivement les libellés en anglais. Le titre et la description d’une page sont traduits ensemble, par paire, afin qu’ils ne puissent jamais se désynchroniser.

Comment une traduction obsolète est détectée#

Par comparaison avec git, et non au moyen d'un indicateur d'état.

Chaque ligne de traduction enregistrée conserve source_hash — le SHA du blob git du fichier source au moment où il a été traduit. La couverture est calculée en lisant l'arborescence du dépôt à la position HEAD et en comparant, pour chaque chemin :

État Signification
current Une traduction automatique existe et son SHA enregistré est égal au SHA du fichier à la position HEAD.
behind Une traduction automatique existe, mais elle correspond à une version plus ancienne de cette page.
missing La page existe dans le dépôt et n'a jamais été traduite dans cette langue.
manual Rédigée manuellement ou importée. La fraîcheur dépend de l'auteur et cette traduction n'est donc jamais considérée comme en retard.
orphaned Une traduction dont le fichier source n'existe plus à la position HEAD.

La couverture est (current + manual) / total, et une langue est synchronisée lorsque behind et missing sont tous deux égaux à zéro. Lorsque le dépôt ne peut pas être lu, la couverture est null — jamais un zéro considéré comme fiable, et chaque interface indique « inconnu » au lieu de signaler à tort une langue saine comme problématique.

La colonne status = 'outdated' de la base de données n'est volontairement pas utilisée à cette fin. Rien dans le produit ne l'alimente automatiquement, elle reste donc à zéro dans chaque espace de travail : un contrôle de fraîcheur fondé sur cette colonne signalerait une santé parfaite pour toujours.

Un passage guidé par cette comparaison traduit les pages en retard avant les pages manquantes. Une traduction obsolète indique activement à un lecteur quelque chose que votre documentation ne dit plus ; une traduction manquante renvoie vers l'original et se contente de ne pas être utile.

Le flux de révision et d’approbation#

Une traduction enregistrée peut avoir trois origines, et elles sont volontairement traitées différemment.

Origine Écrit par Diffusé aux lecteurs Écrasé par une passe ultérieure
docsbook_ai Une passe de traduction Oui Oui
manual_upload Vous, via l’éditeur du panneau ou upload_translation Lisez ceci d’abord Non — une passe automatique ne la remplacera pas
external_api Votre propre pipeline en mode external Lisez ceci d’abord Non

Les téléversements arrivent par défaut à l’état de brouillon. list_pending_translations renvoie les brouillons, approve_translation en fait passer un à l’état de publication, et la modification du contenu d’une traduction marque la ligne comme un téléversement manuel, de sorte qu’une passe ultérieure la laisse inchangée. En mode external, le cycle est le suivant : Docsbook émet translation.needed lorsqu’une page est sur le point d’être traduite, votre pipeline effectue le travail, puis upload_translation renvoie le résultat.

Les traductions automatiques n’entrent pas dans cette file. Une passe écrit les lignes avec le statut auto, et non draft, de sorte que list_pending_translations ne les répertorie jamais. Le flux d’approbation est une porte de contrôle pour les traductions provenant de l’extérieur, et non une étape de révision humaine placée devant la sortie de l’IA. Si vous souhaitez que la sortie de l’IA soit révisée avant d’être visible par les lecteurs, le mode external est celui qui permet de le faire ; le mode auto par défaut publie au fur et à mesure.

Que se passe-t-il lorsqu’une exécution échoue#

Chaque mode d’échec ci-dessous est une décision délibérée visant à servir l’original plutôt qu’à stocker un contenu défectueux.

Échec Ce qui se passe
Le modèle atteint son plafond de tokens de sortie (finish_reason: length) Considéré comme un échec irrécupérable et refusé, il n’est pas stocké. Un fragment tronqué signifiait autrefois qu’une demi-page était mise en cache comme traduction définitive.
Le modèle renvoie un contenu vide Il s’agit également d’un échec irrécupérable. Une chaîne vide propagée comme un succès est à l’origine de l’accumulation de 808 lignes de traduction vides sur un projet.
Un fragment échoue La page est assemblée avec le texte original pour ce fragment et servie uniquement pour cette requête. Elle n’est pas écrite dans Redis, ni dans Postgres, et n’est pas indexée.
La page assemblée est vide alors que la source ne l’est pas Elle n’est pas stockée ; la source est servie à la place.
Un fragment a récemment échoué Un cache négatif de 10 minutes empêche une ruée de nouvelles tentatives. Lors de la prochaine visite après son expiration, seuls les fragments manquants sont retraduits.
Le fournisseur renvoie 402/403 pour la clé partagée de Docsbook Un arrêt global est défini pour 4 heures et chaque exécution en attente s’arrête immédiatement au lieu de solliciter sans relâche un compte épuisé. Les espaces de travail possédant leur propre clé ne sont pas affectés.
Le quota de votre propre clé est épuisé Seule l’exécution de votre projet échoue. Le quota épuisé de quelqu’un d’autre ne vous arrête jamais, et le vôtre ne l’arrête jamais non plus.
Le budget de dépenses du projet est épuisé L’exécution est interrompue avec cette raison explicitement indiquée, et les pages restantes sont traduites lors d’une exécution ultérieure, une fois le solde suffisant. Rien de ce qui a déjà été payé n’est perdu.
L’invocation est interrompue en cours d’exécution La tâche conserve un curseur et un signal de vie. Le processus d’exécution lancé toutes les 2 minutes récupère une tâche silencieuse depuis 15 minutes, libère son verrou et la redémarre à partir de la page suivante non traduite.

Une exécution partiellement terminée est normale, et non un état d’erreur : un site volumineux nécessite plus d’une invocation, chaque invocation progresse aussi loin que son temps d’exécution le permet, puis l’intervalle suivant prend le relais. Ce que vous ne devriez jamais voir, c’est une page à moitié en anglais et à moitié dans une autre langue, car c’est précisément ce type d’assemblage que le code refuse de conserver.

Tant qu’une page n’a pas encore de traduction, le lecteur voit l’original — sans indicateur de chargement, sans erreur et sans bannière promettant une traduction que cette requête ne produit pas. Lorsqu’il n’existe qu’une traduction plus ancienne, le lecteur reçoit immédiatement cette ancienne traduction au lieu de revenir à l’original : un contenu lisible dans la bonne langue vaut mieux que l’attente.

Limites#

  • La cohérence terminologique ne repose sur aucun glossaire. Il n’existe aucune base terminologique, aucune liste de termes à ne pas traduire que vous puissiez fournir, ni aucun contrôle de cohérence entre les pages. La cohérence qui existe provient d’une température de 0, des sections non modifiées servies telles quelles depuis le cache, et du fait que les libellés ainsi que le titre et la description sont traduits en tant qu’ensembles. Deux pages différentes utilisant le même terme ont été traduites indépendamment et peuvent ne pas être cohérentes.
  • « Ne pas traduire les identifiants » est une instruction, pas une garantie. Le code placé entre des clôtures de code et des accents graves est protégé automatiquement. Un identifiant isolé écrit dans une phrase ordinaire — un nom de paramètre dans une phrase, sans accents graves — n’est protégé que par l’invite. Écrire les identifiants entre accents graves est la mesure la plus efficace que vous puissiez prendre pour vos propres traductions.
  • Le texte alt des images reste dans la langue source. Voir ci-dessus ; c’est la conséquence de la protection intégrale des attributs HTML.
  • Une traduction mise en cache a été générée avec la liste de blocage des widgets en vigueur au moment de sa création. Désactiver un widget ne réécrit pas les pages déjà traduites ; elles le prennent en compte lors de leur prochain passage. Recréer la clé du cache en fonction de la liste de blocage entraînerait la retraduction de chaque page dans chaque langue pour un simple changement de présentation.
  • Le mode automatique réagit à un sondage, pas à votre envoi. Voir Paramètres de traduction.

Updated

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