-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial 5 Localization ru
Цель: понять, как LockedIn CLI говорит на 33 языках — и потренироваться направлять агента добавить ещё один. Локализация — фантастическая задача для агента: она достаточно механическая, чтобы делегировать, но у неё есть настоящие ограничения (тестовый барьер, правила раскладки, грамматическое ревью), которые учат вас проверять.
← Назад: Урок 4 Промптинг и ревью · Обратно к Главная
Запустите CLI на испанском, хинди, японском, упрощённом китайском или любом поставляемом языке, и всё меняется — заставка, таблица справки, вывод каждой команды, сессия чата, даже юридический мелкий шрифт. Не только шутки: вся видимая поверхность.
lockedin --lang ru post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh auraЯзык автоопределяется при запуске, разрешается в порядке приоритета:
- флаг
--lang(--lang ru,--lang=fr,-l ja) - переменная окружения
LOCKEDIN_LANG - ваша локаль (
LC_ALL/LC_MESSAGES/LANG, затем локаль ОС/среды выполнения) - английский, как запасной вариант
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 ru переключает на остаток
сессии. Смысл — в аварийном выходе: после переключения он перерисовывает на новом
языке, а затем, на языке, который вы только что покинули, печатает точный путь
обратно — /language en сейчас, lockedin --lang en в следующий раз — чтобы
случайное приземление в 日本語 или ಕನ್ನಡ никогда вас не заперло. (Переключитесь
дважды, и предлагается также язык, который называет ваш LOCKEDIN_LANG.) --lang
и LOCKEDIN_LANG без изменений. Как и /a11y, это искренняя утилита, а не часть
сатиры.
Весь переводимый текст живёт в бандлах, по одному на язык, каждый в форме:
{ meta: { lang: 'ru', 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:
- Сначала план. «Прежде чем писать код, скажи мне файлы, которые ты изменишь, и как ты сохранишь паритет ключей с английским.»
-
Сначала тесты. «Добавь падающие тесты: обнаружение
da, паритет ключей дляda, и датский инвариант reflect/connect. Пока не создавай бандл.» -
Реализация. «Теперь создай
src/content/da.js, переводя существующий бандл ключ за ключом, зарегистрируй его и сделай так, чтобы тесты прошли. Толькоpick/shuffleдля случайности.» -
Барьер + ревью.
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 языках и готовые к большему. Согласны? 👇
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.