-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial 5 Localization es
Meta: entender cómo LockedIn CLI habla 33 idiomas — y practicar dirigir a un agente para añadir otro más. La localización es una tarea excelente para un agente: es lo bastante mecánica para delegarla, pero tiene restricciones reales (una barrera de pruebas, reglas de diseño y revisión gramatical) que te enseñan a revisar.
← Anterior: Tutorial 4 Prompting y revisión · Volver a Inicio
Ejecuta la CLI en español, hindi, japonés, chino simplificado o cualquier idioma incluido y todo cambia — el splash, la tabla de ayuda, la salida de cada comando, la sesión de chat, incluso la letra chica legal. No solo los chistes: toda la superficie visible.
lockedin --lang es post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh auraEl idioma se autodetecta al arrancar, resuelto por orden de prioridad:
- la opción
--lang(--lang es,--lang=fr,-l ja) - la variable de entorno
LOCKEDIN_LANG - tu locale (
LC_ALL/LC_MESSAGES/LANG, luego el locale del sistema) - inglés, como respaldo
normalizeLang() normalmente toma el subtag primario del locale. Así de-DE
selecciona de, pero tlh no se recorta por accidente a tl; los alias
reales fil y tgl apuntan a Tagalog (tl), el noruego nb y nn apuntan
a no, el indonesio histórico in apunta a id, y el código hebreo histórico
iw apunta a he. Dos códigos regionales se conservan tal cual en vez de
plegarse a su subtag primario: pt-BR/pt_BR seleccionan el código regional
canónico mientras que el pt genérico sigue siendo el paquete de portugués de
Brasil compatible con versiones anteriores (ambos son portugués de Brasil y
comparten los mismos pools/UI), y en-SG/en_SG mantienen el singlish (el en
genérico sigue siendo inglés). El chino tradicional de Hong Kong es la misma
clase de excepción: zh-HK, zh_HK.UTF-8 y zh-Hant-HK
seleccionan zh-HK; zh y las etiquetas continentales seleccionan chino
simplificado (zh).
Cambiar sobre la marcha — el panel /language. La CLI siempre pudo arrancar en
otro idioma (--lang, LOCKEDIN_LANG); ahora puedes cambiar a mitad de sesión.
Escribe /language (alias /lang o /languages) para listar los 33 idiomas por
código, cada uno en su propia escritura; /language el cambia por el resto de la sesión.
La gracia es la salida de emergencia: tras el cambio se redibuja en el nuevo idioma y
luego, en el idioma que acabas de dejar, imprime el camino exacto de vuelta —
/language en ahora, lockedin --lang en la próxima vez —, así que aterrizar por
accidente en 日本語 o ಕನ್ನಡ nunca te deja varado. (Cambia dos veces y también se ofrece
el idioma que nombra tu LOCKEDIN_LANG.) --lang y LOCKEDIN_LANG no cambian. Como
/a11y, es una utilidad sincera, no forma parte de la sátira.
Todo el texto traducible vive en paquetes, uno por idioma, cada uno con esta forma:
{ meta: { lang: 'es', name: 'Español', dir: 'ltr' },
pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
ui: { buzzwordDensity: 'Densidad de palabrería: ', /* etiquetas, títulos */ } }-
poolsson los arreglos de contenido (los chistes) que viste en el Cap. 2. -
uison los textos de interfaz: etiquetas, títulos y pequeñas plantillas.
El inglés es el paquete de referencia dentro de src/lockedin.js; los otros 32
módulos viven en 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 y zh-HK
(pt-BR reutiliza los pools/UI de pt pero se registra por separado). Cada uno se
registra en BUNDLES; SUPPORTED_LANGS sale de esas claves, y renderHelp()
imprime esa lista generada. Ningún paquete ui mantiene una lista de códigos a
mano.
setLang('fr'); // apunta el idioma activo al paquete francés
// L = pools activos, U = ui activo
pick(L.HOOKS) // un gancho en francés
U.buzzwordDensity // "Densité de jargon : "Como cada renderizador lee L y U (nunca un string incrustado), setLang
por sí solo cambia toda la experiencia. Ese es todo el truco.
Esta es la invariante que hace seguro añadir un idioma:
Cada paquete debe exponer exactamente las mismas claves
poolsyuique el inglés.
Una prueba lo impone en los 33 paquetes. Si añades un string de UI nuevo en inglés
y olvidas traducirlo en ucraniano, npm test se pone en rojo y te dice qué clave
falta. No puedes publicar en silencio un idioma a medio traducir.
Cada escritura estresa la terminal de una manera distinta:
-
Japonés, chino simplificado y chino tradicional de Hong Kong usan
caracteres East Asian Wide / Fullwidth.
vw()los cuenta como dos columnas, ywrap()corta tokens largos sin espacios para que el texto CJK no rompa tarjetas ni cajas. -
Hindi y kannada usan marcas combinantes no espaciadas o envolventes (
Mn/Me), como matras y viramas.vw()las cuenta como cero columnas para no inflar el ancho medido. -
box()envuelve cada línea antes de rellenarla, así que un banner traducido largo ya no atraviesa el borde. - Cada paquete define
sentenceEndylistSep(por ejemplo./。,,/、) para que las frases compuestas por generadores suenen naturales.
Al añadir un idioma, los strings de encabezado de tarjeta (cardSubtitle,
cardMeta, cardFooter) deben caber en ≤ 60 columnas visibles. Árabe,
persa, hebreo y urdu usan meta.dir: 'rtl'. Por defecto, la salida no incluye controles bidi,
porque algunos terminales los muestran como etiquetas en recuadros.
LOCKEDIN_BIDI=on activa explícitamente aislados equilibrados después del ajuste
solo en terminales que se sabe que los admiten, preservando ANSI, comandos ASCII
y el orden lógico al copiar. La salida accesible siempre los elimina. Sin esa
opción, el orden RTL/LTR mixto puede ser menos sofisticado; no se sondea ni se
infiere compatibilidad.
Algunas plantillas insertan cláusulas crudas del usuario con placeholders como
{cap}. No las traduzcas casilla por casilla: la oración debe seguir funcionando
cuando el placeholder sea una frase que escribió una persona, no un sustantivo
bonito.
Bug real como advertencia: en japonés, poner は justo después de {cap} puede
sonar mal si {cap} es una cláusula completa. La solución no es “traducir con más
ganas”, sino reestructurar la plantilla (por ejemplo, añadir un nominalizador o
mover el placeholder) para que acepte entradas arbitrarias.
El ejercicio sigue funcionando igual. Elige un idioma que puedas verificar (o pídele al agente que lo haga) y llévalo de principio a fin. Escribe la especificación primero:
Añade danés (
da). Creasrc/content/da.jscomo un paquete{ meta, pools, ui }con las mismas claves que el inglés, traduciendo cada entrada (pools de contenido a ~25 cada uno, todos los strings de UI). RegistradaenBUNDLESensrc/lockedin.js.--lang day un localeda-*deben seleccionarlo. Mantén los encabezados de tarjeta dentro del límite de ancho.npm testdebe seguir en verde, y añade pruebas de invariantes y detección en danés como las localizadas existentes.
Luego corre el ciclo de los Capítulos 3–4:
- Plan primero. “Antes de escribir código, dime qué archivos cambiarás y cómo mantendrás la paridad de claves con el inglés.”
-
Pruebas primero. “Añade pruebas que fallen: detección de
da, paridad de claves parada, y una invariante de reflect/connect en danés. Aún no crees el paquete.” -
Implementa. “Ahora crea
src/content/da.jstraduciendo un paquete existente clave por clave, regístralo y haz que las pruebas pasen. Solopick/shufflepara la aleatoriedad.” -
Barrera + revisión.
npm test, luegolockedin --lang da post— y lee el diff: ¿se tradujo cada clave? ¿Siguen alineados los bordes? ¿Las plantillas con{cap}sobreviven a cláusulas crudas del usuario?
Ejercicios de calentamiento más pequeños si un idioma completo es demasiado:
- “Añade un
TAGLINEmás a los 33 paquetes de idioma, manteniendo iguales los conteos.” - “Comprueba que el
cardFooterde kannada sea ≤ 60 columnas visibles y explica cómo mediste las marcas combinantes.” - “Muéstrame la prueba que fallaría si borrara una clave
uideja.js.”
- Ojea
src/content/es.js— sigue siendo una plantilla amable para un paquete nuevo. - Relee
docs/HANDOFF.md→ “Adding a language”. - Disfruta los chistes multilingües en la Referencia de comandos.
Ese es el tutorial completo. Ya puedes dirigir a un agente de IA para construir funciones y localizarlas detrás de una barrera de pruebas — en 33 idiomas y con espacio para más. ¿De acuerdo? 👇
Tutorial
- 1 · Orientation
- 2 · How the Code Works
- 3 · Your First Agent Task
- 4 · Prompting & Reviewing
- 5 · Localization
Reference
Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.