Skip to content

Tutorial 5 Localization it

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

Tutorial 5 · Localizzazione (i18n)

Obiettivo: capire come LockedIn CLI parla 33 lingue — ed esercitarti a dirigere un agente per aggiungerne un'altra. La localizzazione è un task fantastico per un agente: è abbastanza meccanica da delegare, ma ha vincoli reali (una barriera dei test, regole di layout, revisione grammaticale) che ti insegnano a rivedere.

← Precedente: Tutorial 4 Prompt e revisione · Torna a Pagina iniziale


Cosa significa "localizzato" qui

Esegui la CLI in spagnolo, hindi, giapponese, cinese semplificato o qualsiasi lingua inclusa e tutto cambia — lo splash, la tabella della guida, l'output di ogni comando, la sessione di chat, persino la nota legale in piccolo. Non solo le battute: l'intera superficie visibile.

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

La lingua è autorilevata all'avvio, risolta in ordine di priorità:

  1. l'opzione --lang (--lang it, --lang=fr, -l ja)
  2. la variabile d'ambiente LOCKEDIN_LANG
  3. il tuo locale (LC_ALL / LC_MESSAGES / LANG, poi il locale del sistema operativo/runtime)
  4. inglese, come ripiego

normalizeLang() di norma usa il subtag primario del locale. Ciò significa che de-DE seleziona de, ma tlh non diventa per sbaglio tl; gli alias reali fil e tgl puntano intenzionalmente al tagalog (tl), il norvegese nb e nn puntano a no, l'indonesiano storico in punta a id, e il codice ebraico storico iw punta a he. Due codici regionali sono conservati alla lettera anziché ridotti al loro subtag primario: pt-BR/pt_BR selezionano il codice regionale canonico mentre il pt generico resta il bundle di portoghese brasiliano retrocompatibile (entrambi sono portoghese brasiliano e condividono gli stessi pools/UI), e en-SG/en_SG mantengono il singlish (il en generico resta inglese). Il cinese tradizionale di Hong Kong è lo stesso tipo di eccezione: zh-HK, zh_HK.UTF-8 e zh-Hant-HK selezionano zh-HK, mentre il zh generico e le etichette continentali selezionano il cinese semplificato (zh).

Cambiare al volo — il pannello /language. La CLI ha sempre potuto partire in un'altra lingua (--lang, LOCKEDIN_LANG); ora puoi cambiare a metà sessione. Scrivi /language (alias /lang e /languages) per elencare tutte le 33 lingue per codice, ciascuna nella propria scrittura; /language el cambia per il resto della sessione. Il punto è la via di fuga: dopo un cambio ridisegna nella nuova lingua e poi, nella lingua che hai appena lasciato, stampa il percorso esatto per tornare indietro — /language en adesso, lockedin --lang en la prossima volta — così finire per sbaglio in 日本語 o ಕನ್ನಡ non ti lascia mai in panne. (Cambia due volte e viene offerta anche la lingua indicata dal tuo LOCKEDIN_LANG.) --lang e LOCKEDIN_LANG non cambiano. Come /a11y, è un'utilità sincera, non fa parte della satira.

L'idea: i bundle di lingua

Tutto il testo traducibile vive nei bundle, uno per lingua, ognuno con questa forma:

{ meta: { lang: 'it', name: 'Italiano', dir: 'ltr' },
  pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
  ui:    { buzzwordDensity: 'Densità di buzzword: ', /* etichette, titoli */ } }
  • pools sono gli array di contenuti (le battute) che hai incontrato nel Capitolo 2.
  • ui sono le stringhe di interfaccia: etichette, titoli e piccoli template.

L'inglese è il bundle di riferimento dentro src/lockedin.js; gli altri 32 moduli di bundle vivono in 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 e zh-HK (pt-BR riusa i pools/UI di pt ma è registrato separatamente). Ognuno è registrato in BUNDLES; SUPPORTED_LANGS è generato da quelle chiavi, e renderHelp() stampa quella lista di codici generata. Nessun bundle di UI mantiene la lista hardcoded.

setLang('fr');       // punta la lingua attiva al bundle francese
// L = pools attivi, U = ui attiva
pick(L.HOOKS)        // un gancio in francese
U.buzzwordDensity    // "Densité de jargon : "

Poiché ogni renderizzatore legge L e U (mai una stringa hardcoded), il solo setLang cambia l'intera esperienza. È tutto qui il trucco.

La rete di sicurezza: la parità delle chiavi

Ecco l'invariante che rende sicuro aggiungere una lingua:

Ogni bundle deve esporre esattamente le stesse chiavi pools e ui dell'inglese.

Un test lo impone su tutti e 33 i bundle. Se aggiungi una nuova stringa di UI in inglese e dimentichi di tradurla in ucraino, npm test diventa rosso e ti dice quale chiave manca. Non puoi pubblicare in silenzio una lingua tradotta a metà.

La parte difficile: il layout del terminale

Le lingue mettono sotto stress il layout del terminale in modi diversi:

  • Giapponese, cinese semplificato e cinese tradizionale di Hong Kong usano caratteri East Asian Wide / Fullwidth. vw() li conta come due colonne, e wrap() spezza con forza i token lunghi senza spazi così che il testo CJK resti dentro schede e box.
  • Hindi e kannada usano segni combinanti non spaziati o racchiudenti (Mn / Me), come le matra e i virama. vw() li conta come zero colonne così che non gonfino la larghezza misurata.
  • box() manda a capo ogni riga del corpo prima di applicare il padding, così che un banner tradotto lungo non possa più sfondare il bordo.
  • Ogni bundle imposta sentenceEnd e listSep (per esempio . / , , / ) così che le frasi composte dai generatori si leggano in modo naturale.

Quando aggiungi una lingua, le stringhe di intestazione delle schede (cardSubtitle, cardMeta, cardFooter) devono comunque stare entro ≤ 60 colonne visibili. Arabo, persiano, ebraico e urdu impostano meta.dir: 'rtl'. L'output non contiene controlli bidi per impostazione predefinita, perché alcuni terminali li rendono come etichette in riquadri. LOCKEDIN_BIDI=on abilita esplicitamente isolati bilanciati dopo il wrapping per i terminali di cui si sa che li supportano, preservando ANSI, i comandi ASCII e l'ordine logico di copia/incolla. L'output accessibile rimuove sempre quei controlli. Senza l'attivazione esplicita, l'ordinamento misto RTL/LTR può essere meno sofisticato; non sondare né dedurre mai il supporto.

La parte insidiosa: la grammatica attorno all'input grezzo dell'utente

Alcuni template di UI inseriscono clausole grezze dell'utente con placeholder come {cap}. Non tradurli casella per casella. La frase deve restare grammaticale quando il placeholder è una frase digitata dall'utente, non un sostantivo pulito.

Un vero bug di ammonimento: i template giapponesi che mettono subito dopo {cap} possono suonare sbagliati quando {cap} è una clausola completa. La soluzione non è "tradurre con più impegno"; è ristrutturare il template (per esempio, aggiungere un nominalizzatore o spostare il placeholder) così che un input arbitrario dell'utente continui a incastrarsi.

✅ Provaci con il tuo agente — aggiungi una lingua

Questo esercizio funziona esattamente allo stesso modo. Scegli una lingua che puoi verificare (o chiedi all'agente di farlo) e portala dall'inizio alla fine. Scrivi prima la specifica:

Aggiungi il danese (da). Crea src/content/da.js come bundle { meta, pools, ui } con le stesse chiavi dell'inglese, traducendo ogni voce (pool di contenuti a ~25 ciascuno, tutte le stringhe di UI). Registra da in BUNDLES in src/lockedin.js. --lang da e un locale da-* devono selezionarlo. Mantieni le stringhe di intestazione delle schede entro il limite di larghezza. npm test deve restare verde, e aggiungi invarianti danesi + test di rilevamento che rispecchiano quelli localizzati esistenti.

Poi esegui il ciclo dei Capitoli 3–4:

  1. Prima il piano. "Prima di scrivere codice, dimmi quali file cambierai e come manterrai la parità delle chiavi con l'inglese."
  2. Prima i test. "Aggiungi test che falliscono: rilevamento di da, parità delle chiavi per da, e un invariante di reflect/connect in danese. Non creare ancora il bundle."
  3. Implementa. "Ora crea src/content/da.js traducendo un bundle esistente chiave per chiave, registralo e fai passare i test. Solo pick/shuffle per la casualità."
  4. Barriera + revisione. npm test, poi lockedin --lang da post — e leggi il diff: ogni chiave è stata tradotta? I bordi delle schede sono ancora allineati? I template con {cap} sopravvivono alle clausole grezze dell'utente?

Esercizi di riscaldamento più piccoli se un'intera lingua è troppo:

  • "Aggiungi un altro TAGLINE a tutti e 33 i bundle di lingua, mantenendo i conteggi uguali."
  • "Controlla se il cardFooter del kannada è ≤ 60 colonne visibili e spiega come sono stati misurati i segni combinanti."
  • "Mostrami il test che fallirebbe se cancellassi una chiave ui da ja.js."

Dove andare dopo

  • Scorri src/content/es.js — è ancora un template amichevole per un nuovo bundle.
  • Rileggi docs/HANDOFF.md → "Adding a language".
  • Goditi le battute multilingue nel Riferimento dei comandi.

Questo è il tutorial completo. Ora sai dirigere un agente di IA per costruire funzionalità e localizzarle dietro una barriera dei test — in 33 lingue e pronto per altre. D'accordo? 👇

📘 LockedIn CLI wiki

Tutorial

Reference


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

Clone this wiki locally