Le fichier de verrouillage
Ce que verbatra.lock.json enregistre, comment la dérive est détectée, comment les exécutions concurrentes sont sérialisées, et pourquoi tu le commites.
Page traduite automatiquement
Le fichier de verrouillage, verbatra.lock.json, existe pour qu'une exécution sache ce qui a déjà
été traduit et le saute : c'est la référence avec laquelle chaque exécution compare, et c'est ce
qui rend verbatra incrémental. Cette page couvre ce qu'il stocke, comment il change, et ce qui se
passe quand il est disputé, absent ou corrompu.
Ce qu'il enregistre
Pour chaque locale cible, le fichier de verrouillage stocke un hash de contenu par clé traduite,
calculé à partir de la valeur source qui a produit la traduction existante. Il ne contient aucune
traduction et aucun secret : juste un champ version et des hashs. Le hash normalise l'Unicode en
NFC et les fins de ligne en LF, donc réenregistrer un fichier source avec une normalisation
différente ou des fins de ligne CRLF ne marque rien comme modifié.
Comment la dérive est détectée
Quand une exécution compare une locale cible, une clé source absente de la cible est manquante. Pour une clé que la cible possède, le hash source actuel est comparé au hash que le fichier de verrouillage a enregistré : une différence signifie que la source a dérivé depuis la dernière traduction de la clé, donc elle est modifiée et se fait retraduire ; une correspondance signifie qu'elle est inchangée et n'est jamais envoyée au fournisseur. C'est pourquoi une seconde exécution sans modification de la source n'appelle le fournisseur pour rien, et pourquoi des traductions périmées ne peuvent pas se cacher derrière une clé qui existe simplement. Le pipeline complet est sur Comment ça marche.
Adopter un projet existant
Pointer verbatra vers un dépôt dont les fichiers de locale contiennent déjà des traductions relues ne les retraduit pas. À la première exécution il n'y a pas de fichier de verrouillage, donc aucune clé ne peut être détectée comme périmée : une clé source que le fichier cible possède déjà est inchangée, n'est jamais envoyée au fournisseur et garde sa valeur existante. Seules les clés que le fichier cible n'a pas sont manquantes, et seules celles-là sont traduites. Si pour une locale aucune traduction n'a été acceptée, aucune clé supprimée et aucune forme générée, son fichier cible existant n'est pas réécrit du tout.
L'exécution enregistre quand même le hash source actuel pour chaque clé que la cible contient : la première exécution est donc l'étape d'adoption elle-même. Elle établit la référence sans un seul appel au fournisseur, et à partir de la deuxième exécution les modifications de la source ressortent comme dérive de façon normale.
Qu'une clé soit adoptée se décide par sa présence, jamais par sa valeur, ce qui a deux conséquences à connaître avant cette première exécution :
- Une valeur vide ou non traduite compte comme traduite. Une valeur cible qui est une chaîne vide, ou qui est encore le texte source non traduit, est une clé qui existe : elle est donc inchangée et ne sera jamais remplie. Les outils de scaffolding qui pré-créent les fichiers de locale avec des chaînes vides tombent exactement là-dessus. La solution est de supprimer la clé du fichier cible : vider sa valeur ne sert à rien, car une chaîne vide reste une entrée. Une fois la clé partie, l'exécution suivante la voit comme manquante et la traduit.
- Une traduction déjà périmée est enregistrée comme à jour. Le fichier de verrouillage prend le hash source tel qu'il est maintenant, donc une traduction qui avait déjà dérivé de la source avant l'adoption du projet est tenue pour à jour et ne sera pas revue. Corrige ou supprime ces clés avant la première exécution.
La génération de pluriels suit la même règle d'adoption. Une forme plurielle que le fichier cible
contient déjà et que verbatra n'a pas générée est gardée telle quelle : elle n'est ni régénérée ni
envoyée au fournisseur (une forme que le fichier de verrouillage suit déjà est bien régénérée quand
sa source change). Tu peux donc laisser generatePlurals activé pendant que tu adoptes un projet
qui porte des formes plurielles écrites à la main ; seules les formes réellement absentes de la
cible sont synthétisées.
Tu peux voir tout cela avant de dépenser quoi que ce soit : verbatra diff liste par locale les
clés manquantes et modifiées exactes, verbatra check rapporte la même chose sous forme de
compteurs, et verbatra translate --dry-run te donne le résumé complet de l'exécution. Aucun des
trois n'appelle de fournisseur, n'écrit de fichier de locale ni n'écrit le fichier de
verrouillage.
Comment il est mis à jour
Le fichier de verrouillage est mis à jour par locale, et la façon dépend de ce qui a tourné :
- Une exécution complète (translate, watch, ou un import de classeur) remplace en bloc les entrées de cette locale par le résultat autoritaire de l'exécution.
- Une action sur une seule clé (comme une retraduction depuis Studio) fusionne uniquement l'entrée de cette clé, en laissant chaque autre clé enregistrée intacte.
Dans les deux cas une exception s'applique : une clé retenue pendant cette exécution (un contrôle d'intégrité échoué, un appel fournisseur échoué, ou une source ICU invalide) garde son hash précédent, pour que l'exécution suivante la voie toujours comme demandant du travail et la retente au lieu de l'enregistrer comme faite. Les clés orphelines ne reçoivent aucune entrée. Le fichier est sérialisé avec des clés triées, pour que ses diffs restent stables et relisibles.
Le verrou d'écriture
Deux exécutions touchant la même locale au même moment (un second terminal, un job CI, une action Studio) pourraient sinon comparer toutes deux avec une référence périmée et payer toutes deux le même appel fournisseur. Pour l'empêcher, chaque écriture d'une locale et de ses entrées de verrouillage se fait sous un verrou d'écriture inter-processus limité à cette seule locale ; un second rédacteur pour la même locale attend, puis relit le fichier de verrouillage à frais et compare avec une référence qui inclut déjà le résultat du premier rédacteur. Des locales différentes ne se bloquent pas entre elles.
Quand une exécution traduit plusieurs locales à la fois et rencontre une erreur globale (en pratique un fichier de verrouillage corrompu), elle arrête de réclamer de nouvelles locales et attend la fin de celles qui tournent déjà, donc chaque verrou pris par l'exécution est libéré avant que la commande ne sorte. Aucune locale n'est démarrée après que l'exécution a déjà échoué, et aucun verrou n'est rendu orphelin par l'échec lui-même.
Si un verrou ne peut pas être acquis, l'exécution échoue avec LOCK_CONTENDED et nomme le chemin
du fichier de verrou (sous le répertoire .verbatra-local/, ignoré par git). Si aucun processus
verbatra ne tourne, ce fichier a été laissé par un processus tué : supprime-le et réessaie.
Absent ou corrompu
Un fichier de verrouillage absent n'est pas une erreur : c'est une première exécution, et sans
référence rien ne peut être détecté comme périmé. Les clés source que le fichier cible n'a pas sont
manquantes et se font traduire ; celles qu'il a sont inchangées et restent intactes, comme décrit
plus haut à propos de l'adoption. Un fichier de verrouillage présent mais inanalysable,
structurellement faux, trop gros ou à une version non prise en charge fait échouer l'exécution avec
LOCK_FILE_INVALID au lieu d'être écrasé en silence, pour que tu puisses l'inspecter ou le
restaurer plutôt que de perdre la référence.
Commite-le
Commite verbatra.lock.json avec tes fichiers de locale. C'est la référence partagée avec laquelle
tes coéquipiers et ta CI comparent ; le garder sous contrôle de version est ce qui rend les
exécutions incrémentales reproductibles d'une machine à l'autre. Ne le modifie jamais à la main.
Commiter les deux est aussi ce qui rend un retour en arrière possible. Comme le fichier de verrouillage enregistre des hashs de la source et rien sur les valeurs traduites, si tu reviens en arrière sur tes fichiers de locale sans lui, il continuera d'affirmer que les traductions restaurées sont à jour, et rien ne les retraduira. Voir Récupération et retour en arrière.
Edit on GitHub