Skip to content

Tutorial 5 Localization uk

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

Урок 5 · Локалізація (i18n)

Мета: зрозуміти, як LockedIn CLI говорить 33 мовами — і потренуватися скеровувати агента додати ще одну. Локалізація — фантастичне завдання для агента: воно достатньо механічне, щоб делегувати, але має справжні обмеження (тестовий бар'єр, правила розкладки, граматичне рев'ю), що вчать вас перевіряти.

← Назад: Урок 4 Промптинг і рев'ю · Назад до Головна


Що тут означає «локалізовано»

Запустіть CLI іспанською, гінді, японською, спрощеною китайською чи будь-якою поставленою мовою, і все змінюється — заставка, таблиця довідки, вивід кожної команди, сесія чату, навіть юридичний дрібний шрифт. Не лише жарти: уся видима поверхня.

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

Мова автовизначається під час запуску, розв'язується в порядку пріоритету:

  1. прапорець --lang (--lang uk, --lang=fr, -l ja)
  2. змінна оточення LOCKEDIN_LANG
  3. ваша локаль (LC_ALL / LC_MESSAGES / LANG, потім локаль ОС/середовища виконання)
  4. англійська, як запасний варіант

normalizeLang() зазвичай використовує основний subtag локалі. Це означає, що de-DE обирає de, але tlh не стає випадково tl; справжні аліаси fil і tgl навмисно відображаються в тагальську (tl), норвезькі nb і nn відображаються в no, застаріла індонезійська in відображається в id, а застарілий іврит iw відображається в he. Два регіональні коди зберігаються дослівно, а не згортаються до основного subtag: pt-BR/pt_BR обирають канонічний регіональний код, тоді як загальний pt лишається зворотно сумісним бандлом бразильської португальської (обидва — бразильська португальська й розділяють одні pools/UI), а en-SG/en_SG зберігають синглиш (загальний en лишається англійською). Гонконгська традиційна китайська — те саме виключення: zh-HK, zh_HK.UTF-8 і zh-Hant-HK обирають zh-HK, тоді як загальний zh і материкові теги обирають спрощену китайську (zh).

Перемикання на льоту — панель /language. CLI завжди міг стартувати іншою мовою (--lang, LOCKEDIN_LANG); тепер ви можете перемикатися посеред сесії. Надрукуйте /language (аліаси /lang і /languages), щоб перелічити всі 33 мови за кодом, кожну своїм письмом; /language uk перемикає на решту сесії. Сенс — в аварійному виході: після перемикання він перемальовує новою мовою, а потім, мовою, яку ви щойно покинули, друкує точний шлях назад — /language en зараз, lockedin --lang en наступного разу — щоб випадкове приземлення в 日本語 чи ಕನ್ನಡ ніколи вас не замкнуло. (Перемкніться двічі, і пропонується також мова, яку називає ваш LOCKEDIN_LANG.) --lang і LOCKEDIN_LANG без змін. Як і /a11y, це щира утиліта, а не частина сатири.

Ідея: мовні бандли

Увесь перекладний текст живе в бандлах, по одному на мову, кожен у формі:

{ meta: { lang: 'uk', name: 'Українська', dir: 'ltr' },
  pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
  ui:    { buzzwordDensity: 'Щільність buzzwords: ', /* labels, headings */ } }
  • pools — це масиви контенту (жарти), які ви зустріли в Розділі 2.
  • ui — це рядки «обв'язки»: мітки, заголовки й невеликі шаблони.

Англійська — це еталонний бандл усередині src/lockedin.js; інші 32 модулі бандлів живуть у 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 і zh-HK (pt-BR перевикористовує pools/UI з pt, але реєструється окремо). Кожен зареєстрований у BUNDLES; SUPPORTED_LANGS генерується з цих ключів, і renderHelp() друкує цей згенерований список кодів. Жоден UI-бандл не хардкодить список.

setLang('fr');       // вказати активну мову на французький бандл
// L = активні pools, U = активний ui
pick(L.HOOKS)        // французький hook
U.buzzwordDensity    // "Densité de jargon : "

Оскільки кожен рендерер читає L і U (ніколи захардкожений рядок), один setLang міняє весь досвід. У цьому весь фокус.

Страхувальна сітка: паритет ключів

Ось інваріант, що робить додавання мови безпечним:

Кожен бандл має надавати точно ті самі ключі pools і ui, що й англійський.

Тест забезпечує це по всіх 33 бандлах. Якщо ви додасте новий UI-рядок в англійський і забудете перекласти його українською, npm test стане червоним і скаже вам, який ключ відсутній. Ви не можете мовчки викотити наполовину перекладену мову.

Важка частина: розкладка терміналу

Мови навантажують розкладку терміналу по-різному:

  • Японська, спрощена китайська й гонконгська традиційна китайська використовують символи East Asian Wide / Fullwidth. vw() рахує їх за два стовпці, а wrap() жорстко переносить довгі токени без пробілів, щоб текст CJK лишався всередині карток і рамок.
  • Гінді та каннада використовують непробільні/охопні комбіновані знаки (Mn / Me), такі як matra й virama. vw() рахує їх за нуль стовпців, щоб вони не роздували виміряну ширину.
  • box() переносить кожен рядок тіла перед додаванням відступів, тож довгий перекладений банер більше не може пробити рамку.
  • Кожен бандл задає sentenceEnd і listSep (наприклад . / , , / ), щоб складені генератором речення читалися природно.

Коли ви додаєте мову, рядки заголовка картки (cardSubtitle, cardMeta, cardFooter) усе одно мають вміщатися в ≤ 60 видимих стовпців. Арабська, перська, іврит та урду задають meta.dir: 'rtl'. Вивід не містить bidi-керівних символів за замовчуванням, бо деякі термінали рендерять їх як мітки в рамках. LOCKEDIN_BIDI=on явно вмикає збалансовані isolates після перенесення для терміналів, про які відомо, що вони їх підтримують, зберігаючи ANSI, ASCII-команди й логічний порядок копіювання/вставлення. Доступний вивід завжди прибирає ці керівні символи. Без явного увімкнення змішаний порядок RTL/LTR може бути менш витонченим; ніколи не зондуйте й не виводьте підтримку.

Підступна частина: граматика навколо сирого вводу користувача

Деякі UI-шаблони вставляють сирі користувацькі фрази з плейсхолдерами на кшталт {cap}. Не перекладайте їх слот-у-слот. Речення має лишатися граматичним, коли плейсхолдер — це фраза, яку надрукував користувач, а не охайний іменник.

Реальний застережний баг: японські шаблони, що ставлять одразу після {cap}, можуть звучати неправильно, коли {cap} — це повне речення. Виправлення не «перекладати старанніше»; це перебудувати шаблон (наприклад, додати номіналізатор чи перемістити плейсхолдер), щоб довільний користувацький ввід усе ще підходив.

✅ Спробуйте зі своїм агентом — додайте мову

Ця вправа все ще працює точно так само. Оберіть мову, яку ви можете перевірити на здоровий глузд (чи попросіть агента), і проведіть її від початку до кінця. Спершу напишіть специфікацію:

Додайте данську (da). Створіть src/content/da.js як бандл { meta, pools, ui } із тими самими ключами, що й англійський, переклавши кожен запис (пули контенту по ~25 кожен, усі UI-рядки). Зареєструйте da в BUNDLES у src/lockedin.js. --lang da і локаль da-* мають його обирати. Тримайте рядки заголовка картки в межах ліміту ширини. npm test має лишатися зеленим, і додайте інваріанти для данської + тести виявлення, що віддзеркалюють наявні локалізовані.

Потім проженіть цикл із Розділів 3–4:

  1. Спершу план. «Перш ніж писати код, скажи мені файли, які ти зміниш, і як ти збережеш паритет ключів з англійською.»
  2. Спершу тести. «Додай падаючі тести: виявлення da, паритет ключів для da, і данський інваріант reflect/connect. Поки не створюй бандл.»
  3. Реалізація. «Тепер створи src/content/da.js, перекладаючи наявний бандл ключ за ключем, зареєструй його й зроби так, щоб тести пройшли. Лише pick/shuffle для випадковості.»
  4. Бар'єр + рев'ю. npm test, потім lockedin --lang da post — і прочитайте diff: чи перекладено кожен ключ? Чи все ще вирівнюються рамки карток? Чи виживають шаблони з {cap} на сирих користувацьких фразах?

Менші розминочні вправи, якщо ціла мова — це забагато:

  • «Додай ще один TAGLINE в усі 33 мовні бандли, зберігаючи кількість рівною.»
  • «Перевір, чи ≤ 60 видимих стовпців у cardFooter каннада, і поясни, як вимірювалися комбіновані знаки.»
  • «Покажи мені тест, що впав би, якби я видалив ключ ui з ja.js

Куди йти далі

  • Пробіжіться src/content/es.js — він усе ще дружній шаблон для нового бандла.
  • Перечитайте docs/HANDOFF.md → «Adding a language».
  • Насолодіться багатомовними жартами в Довіднику команд.

Це повний посібник. Ви тепер вмієте скеровувати ШІ-агента будувати функції і локалізувати їх за тестовим бар'єром — 33 мовами й готові до більшого. Погоджуєтеся? 👇

📘 LockedIn CLI wiki

Tutorial

Reference


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

Clone this wiki locally