Skip to content

Tutorial 5 Localization fr

James Morris edited this page Jul 29, 2026 · 1 revision

Tutoriel 5 · Localisation (i18n)

Objectif : comprendre comment LockedIn CLI parle 33 langues — et s'exercer à diriger un agent pour en ajouter une autre. La localisation est une tâche formidable pour un agent : elle est assez mécanique pour être déléguée, mais elle a de vraies contraintes (une barrière de tests, des règles de mise en page, une revue grammaticale) qui vous apprennent à relire.

← Précédent : Tutoriel 4 Prompting et revue · Retour à Accueil


Ce que « localisé » signifie ici

Lancez la CLI en espagnol, en hindi, en japonais, en chinois simplifié ou dans n'importe quelle langue livrée et tout change — l'écran d'accueil, la table d'aide, la sortie de chaque commande, la session de chat, même les mentions légales. Pas seulement les blagues : toute la surface visible.

lockedin --lang fr post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh aura

La langue est autodétectée au démarrage, résolue par ordre de priorité :

  1. l'option --lang (--lang fr, --lang=fr, -l ja)
  2. la variable d'environnement LOCKEDIN_LANG
  3. votre locale (LC_ALL / LC_MESSAGES / LANG, puis le locale du système/de l'exécution)
  4. l'anglais, comme repli

normalizeLang() utilise normalement le sous-tag primaire du locale. Cela signifie que de-DE sélectionne de, mais tlh ne devient pas accidentellement tl ; les vrais alias fil et tgl pointent intentionnellement vers le tagalog (tl), le norvégien nb et nn pointent vers no, l'indonésien historique in pointe vers id, et l'hébreu historique iw pointe vers he. Deux codes régionaux sont conservés tels quels plutôt que repliés sur leur sous-tag primaire : pt-BR/pt_BR sélectionnent le code régional canonique tandis que le pt générique reste le paquet de portugais brésilien rétrocompatible (les deux sont du portugais brésilien et partagent les mêmes pools/UI), et en-SG/en_SG conservent le singlish (le en générique reste l'anglais). Le chinois traditionnel de Hong Kong est le même genre d'exception : zh-HK, zh_HK.UTF-8 et zh-Hant-HK sélectionnent zh-HK, tandis que le zh générique et les tags continentaux sélectionnent le chinois simplifié (zh).

Changer en cours de route — le panneau /language. La CLI pouvait toujours démarrer dans une autre langue (--lang, LOCKEDIN_LANG) ; désormais, vous pouvez changer en pleine session. Tapez /language (alias /lang et /languages) pour lister les 33 langues par code, chacune dans sa propre écriture ; /language el change pour le reste de la session. L'intérêt, c'est la porte de sortie : après un changement, l'interface se redessine dans la nouvelle langue puis, dans la langue que vous venez de quitter, affiche le chemin exact du retour — /language en maintenant, lockedin --lang en la prochaine fois — de sorte qu'atterrir par accident dans 日本語 ou ಕನ್ನಡ ne vous laisse jamais en rade. (Changez deux fois et la langue nommée par votre LOCKEDIN_LANG est proposée aussi.) --lang et LOCKEDIN_LANG sont inchangés. Comme /a11y, c'est un utilitaire sincère, qui ne fait pas partie de la satire.

L'idée : les paquets de langue

Tout le texte traduisible vit dans des paquets, un par langue, chacun de la forme :

{ meta: { lang: 'fr', name: 'Français', dir: 'ltr' },
  pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
  ui:    { buzzwordDensity: 'Densité de jargon : ', /* étiquettes, titres */ } }
  • pools sont les tableaux de contenu (les blagues) que vous avez rencontrés au Chapitre 2.
  • ui sont les chaînes d'habillage : étiquettes, titres et petits gabarits.

L'anglais est le paquet de référence à l'intérieur de src/lockedin.js ; les 32 autres modules de paquet vivent dans src/content/*.js : ar, bn, bo, de, el, en-SG, es, eu, fa, fi, fr, he, hi, id, is, it, ja, kn, ms, nl, no, pl, pt, pt-BR, ru, sv, tl, tr, uk, ur, zh et zh-HK (pt-BR réutilise les pools/UI de pt mais est enregistré séparément). Chacun est enregistré dans BUNDLES ; SUPPORTED_LANGS est généré à partir de ces clés, et renderHelp() affiche cette liste de codes générée. Aucun paquet UI ne code la liste en dur.

setLang('fr');       // pointe la langue active sur le paquet français
// L = pools actifs, U = ui actif
pick(L.HOOKS)        // un hook en français
U.buzzwordDensity    // "Densité de jargon : "

Parce que chaque moteur de rendu lit L et U (jamais une chaîne codée en dur), setLang à lui seul change toute l'expérience. C'est là tout le truc.

Le filet de sécurité : la parité des clés

Voici l'invariant qui rend l'ajout d'une langue sûr :

Chaque paquet doit exposer exactement les mêmes clés pools et ui que l'anglais.

Un test l'impose sur les 33 paquets. Si vous ajoutez une nouvelle chaîne d'UI en anglais et oubliez de la traduire en ukrainien, npm test passe au rouge et vous indique quelle clé manque. Vous ne pouvez pas livrer en silence une langue à moitié traduite.

La partie difficile : la mise en page du terminal

Les langues sollicitent la mise en page du terminal de différentes façons :

  • Le japonais, le chinois simplifié et le chinois traditionnel de Hong Kong utilisent des caractères East Asian Wide / Fullwidth. vw() les compte pour deux colonnes, et wrap() coupe brutalement les longs tokens sans espace pour que le texte CJK reste à l'intérieur des cartes et des boîtes.
  • Le hindi et le kannada utilisent des marques combinantes sans chasse ou englobantes (Mn / Me), comme les matras et les viramas. vw() les compte pour zéro colonne afin qu'elles ne gonflent pas la largeur mesurée.
  • box() enveloppe chaque ligne de corps avant de la remplir, si bien qu'une longue bannière traduite ne peut plus percer la bordure.
  • Chaque paquet définit sentenceEnd et listSep (par exemple . / , , / ) pour que les phrases composées par les générateurs se lisent naturellement.

Quand vous ajoutez une langue, les chaînes d'en-tête de carte (cardSubtitle, cardMeta, cardFooter) doivent toujours tenir dans ≤ 60 colonnes visibles. L'arabe, le persan, l'hébreu et l'ourdou définissent meta.dir: 'rtl'. La sortie ne contient aucun contrôle bidi par défaut, car certains terminaux les affichent comme des étiquettes encadrées. LOCKEDIN_BIDI=on active explicitement des isolats équilibrés après le retour à la ligne pour les terminaux connus pour les prendre en charge, en préservant l'ANSI, les commandes ASCII et l'ordre logique de copier-coller. La sortie accessible retire toujours ces contrôles. Sans cette activation volontaire, l'ordre mixte RTL/LTR peut être moins sophistiqué ; ne sondez jamais et n'inférez jamais la prise en charge.

La partie sournoise : la grammaire autour de la saisie brute de l'utilisateur

Certains gabarits d'UI insèrent des clauses brutes de l'utilisateur avec des placeholders comme {cap}. Ne les traduisez pas emplacement par emplacement. La phrase doit rester grammaticale quand le placeholder est une expression tapée par l'utilisateur, et non un joli nom.

Un vrai bug qui doit servir d'avertissement : les gabarits japonais qui placent juste après {cap} peuvent sonner faux quand {cap} est une clause entière. La solution n'est pas de « traduire plus fort » ; c'est de restructurer le gabarit (par exemple, ajouter un nominalisateur ou déplacer le placeholder) pour qu'une saisie utilisateur arbitraire s'y insère toujours.

✅ Essayez avec votre agent — ajoutez une langue

Cet exercice fonctionne toujours exactement de la même façon. Choisissez une langue que vous pouvez vérifier (ou demandez à l'agent de le faire), et menez-la de bout en bout. Écrivez d'abord la spéc :

Ajoutez le danois (da). Créez src/content/da.js comme un paquet { meta, pools, ui } avec les mêmes clés que l'anglais, en traduisant chaque entrée (pools de contenu à ~25 chacun, toutes les chaînes d'UI). Enregistrez da dans BUNDLES dans src/lockedin.js. --lang da et un locale da-* doivent le sélectionner. Gardez les chaînes d'en-tête de carte dans la limite de largeur. npm test doit rester au vert, et ajoutez des invariants + tests de détection en danois qui reflètent ceux, localisés, existants.

Ensuite, exécutez la boucle des Chapitres 3–4 :

  1. Le plan d'abord. « Avant d'écrire du code, dis-moi les fichiers que tu vas changer et comment tu maintiendras la parité des clés avec l'anglais. »
  2. Les tests d'abord. « Ajoute des tests qui échouent : la détection de da, la parité des clés pour da, et un invariant reflect/connect en danois. Ne crée pas encore le paquet. »
  3. Implémentez. « Maintenant, crée src/content/da.js en traduisant un paquet existant clé par clé, enregistre-le, et fais passer les tests. Uniquement pick/shuffle pour l'aléatoire. »
  4. Barrière + revue. npm test, puis lockedin --lang da post — et lisez le diff : chaque clé a-t-elle été traduite ? Les bordures de carte s'alignent-elles toujours ? Les gabarits avec {cap} survivent-ils aux clauses brutes de l'utilisateur ?

Des exercices d'échauffement plus petits si une langue entière est de trop :

  • « Ajoute un TAGLINE de plus aux 33 paquets de langue, en gardant les comptes égaux. »
  • « Vérifie si le cardFooter du kannada fait ≤ 60 colonnes visibles et explique comment les marques combinantes ont été mesurées. »
  • « Montre-moi le test qui échouerait si je supprimais une clé ui de ja.js. »

Où aller ensuite

  • Survolez src/content/es.js — c'est toujours un gabarit accueillant pour un nouveau paquet.
  • Relisez docs/HANDOFF.md → « Adding a language ».
  • Profitez des blagues multilingues dans la Référence des commandes.

Voilà le tutoriel complet. Vous pouvez désormais diriger un agent IA pour construire des fonctionnalités et les localiser derrière une barrière de tests — en 33 langues et prêt pour davantage. D'accord ? 👇

📘 LockedIn CLI wiki

Tutorial

Reference


Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.

Clone this wiki locally