5 Commits
Author SHA1 Message Date
Rohit Ghumare d86fedaa51 fix: dark-mode mermaid fills, Apple Silicon Docker build, fnm unzip, ROADMAP rows, site chrome translations (#477)
* fix: dark-mode mermaid fills, Apple Silicon Docker build, fnm unzip, ROADMAP rows, site chrome translations

- site/lesson.html: mermaidPreprocess handles 3-digit hex fills so fill:#dfd stays legible in dark mode (#433)
- 07-docker-for-ai: pin FROM to linux/amd64 and document why the cu124 layer fails on Apple Silicon (#476)
- 01-dev-environment: add unzip to the apt line, fnm's installer needs it (#473)
- ROADMAP.md: add Phase 11 lessons 16 and 17, 521 rows to 523
- site: translate interface strings for the eight CI languages via ui-i18n.js + ui-strings.js, picker dispatches aifs:lang, drift guarded by test_ui_i18n.js in CI (#469, #404)

* docs: describe fnm's unzip check and scope the CUDA image to x86_64 hosts

- 01-dev-environment: the installer checks for unzip up front and exits with its own message; macOS goes through Homebrew
- 07-docker-for-ai: the linux/amd64 pin means the image is for x86_64 Linux hosts with an NVIDIA GPU

* feat(i18n): generate site chrome translations in the translate pipeline

The hand dictionary becomes site/ui-strings.json: an English key list plus
per-language overrides. scripts/translate_ui_strings.py fills every other key
through the lesson translator's provider layer, reuses what is already
published, protects file names, paths, and commands behind the same
placeholders, and writes i18n/<lang>/ui.json. A new ui-strings job in
translate.yml runs it per CI language and publishes to the translations
branch with the same race-safe worktree loop, so a new label or a new
language needs no translation written by hand.

site/ui-i18n.js now fetches i18n/<lang>/ui.json from the translations branch
at runtime, caches it per language, and falls back to English until a language
is published. Tests cover source consistency, precedence, placeholder
protection, the page drift guard, and the fetch path.

* fix(i18n): retranslate keys whose override was removed and keep failed dictionary loads retryable

- ui.json now carries {strings, pinned}; a key that was pinned in the last publication but has no override now is translated again instead of reusing the old pin
- the runtime no longer caches a failed fetch, so a language published later is picked up on the next switch without a reload

* fix(i18n): refresh flat ui.json values once when pin provenance is missing

A flat published file predates the {strings, pinned} shape and cannot say
which values came from overrides, so every value in it counts as pinned and
is retranslated on the first run instead of being reused blindly.
2026-09-24 09:22:11 +05:30
Rohit Ghumare 6cdb135c5c feat: add AI Engineering Learning Paths (#444) 2026-08-30 09:53:30 +01:00
Rohit Ghumare cd5bd53d82 fix(i18n): make translation publishing retry-safe (#401) 2026-08-09 19:13:33 +01:00
Rohit Ghumare 7953bfad74 fix(i18n): shard translation CI by phase + commit README translations + fix language picker (#387)
* fix(i18n): shard translation CI by phase, commit README translations, limit picker to supported languages

The translate workflow ran one job per language, but a full 503-lesson language
run is ~27h on a CPU runner. Every job hit the 5.5h limit and was killed before
its publish step, so it banked nothing and the translations branch never got
created: it would retry and die forever.

CI sharding
- Matrix is now one job per (language, phase). The largest phase (19, 85
  lessons) is ~4.5h, comfortably under the limit; most are 1-1.6h. max-parallel
  raised to 20.
- Cache is per-(language, phase) (i18n/<lang>/.cache/<phase>.json) and each job
  publishes only its own i18n/<lang>/phases/<phase>/ slice, so disjoint shards
  merge without clobbering. translate_lessons.py gains --phase __root__ for the
  README and a per-phase cache path.

README translations (committed to main, not CI)
- scripts/build_readme_i18n.py rebuilds i18n/<lang>/README.md by replacing only
  the translated line-spans in a copy of the English README; the banner, badges,
  584-row lesson table, and every link are preserved byte-for-byte (round-trip
  identity asserted every run). Root-relative links are rewritten to resolve two
  levels deep.
- scripts/readme_translations.py holds hand-authored translations (highest
  quality for a landing page) for 12 languages: es, fr, pt, de, it, zh, ja, ko,
  hi, ar, ru, tr. Unmapped blocks fall back to English.
- README language bar points at the committed files and lists all 12. i18n/
  README.md is un-ignored; lesson artifacts stay ignored.
- CI guard: build_readme_i18n.py --check fails on drift; the counts bot
  regenerates them when it syncs the English stats block.

Language picker
- build.js emits only source + ci:true languages into langs.js, so the site
  switcher offers only languages the site can actually serve (English + the 5
  ci languages) instead of all 40 registry entries. Cache-bust bumped.

Fixes the timed-out run in the translate workflow.

* feat(learning): AI-native learning flow, learn-first homepage, evidence-backed learner wall

The course gains a terminal-first learning experience driven by any coding
agent, and the homepage leads with it.

Learning skills (skills/ canonical, .claude/skills/ mirror for cloners)
- start-learning: one-time onboarding. Three-question interview, placement
  quiz, writes LEARNING.md (mission, entry phase, 20-phase path, progress log,
  review queue) that every later session reads and updates.
- learn: the tutor loop. Warm-up recall from the previous lesson's quiz, then
  the next lesson taught interactively (problem, concept, build, use), then the
  post-stage quiz, then progress recorded. Works cloned or entirely over
  raw.githubusercontent.com; no setup required.
- course-guide: topic router over the README contents. A topic, question, or
  bug in; the exact lessons plus the right next command out.
- find-your-level: 503-lesson count, agent-neutral question flow, raw-fetch
  fallback for ROADMAP.md, hand-off to start-learning/learn.
- check-understanding: no-clone fallback fetching lesson docs from raw.
- npx skills add rohitg00/ai-engineering-from-scratch installs exactly these
  five for any SKILL.md agent (verified against this tree: 5 found, no dupes,
  none of the 388 lesson artifacts). CI guard: skills/ and .claude/skills/
  must stay identical.

README
- "Start learning in 30 seconds" section up top; Getting Started reordered
  with terminal learning as Option A; skills table covers all five; the
  toolkit section no longer claims npx installs the 388 outputs (it never
  did; they install via scripts/install_skills.py).

Homepage
- Masthead install card: the two-command flow with real agent marks and a
  copy chip (icon, hover invert, press scale, copied state, clipboard
  fallback). Colophon "cp" button upgraded to the same component and its
  label-swap no longer destroys the icon.
- Cycling figure plate fills the masthead's empty right side and explains
  the course: FIG_001 forward pass draws itself and runs signal pulses;
  FIG_002 types out a /learn agent session with a blinking caret; FIG_003
  learning curves with graph grid, area fill, on-curve milestone markers
  (computed on the bezier), axis arrowheads, and a rider dot. Sequential
  fade between plates so text can never double-expose; fixed per-tier
  width/offset so the plate never clips at any viewport; reduced-motion
  shows a static plate.
- Learner wall: seamless JS-filled marquee (clones halves until the loop
  covers any viewport, constant scroll speed, no blank gaps) with real
  marks for every name that has a redistributable SVG (simple-icons plus
  official Wikimedia files in site/logos/); IIT Bombay and Windsor are
  type-set because only fair-use logos exist. Anonymized pull quote from a
  Google AI engineer beneath. Grayscale with dark-theme invert.
- Mobile: command wraps instead of horizontal scrolling.
2026-08-02 21:57:30 +01:00
Rohit Ghumare 3227f17628 feat(i18n): free NLLB-200 translation pipeline, zero repo bloat (#379)
English stays canonical. Translations generate to a separate translations
branch (never main); the site, README, and books all consume them. Default
engine is NLLB-200 in the CI runner: no API key, no Vercel cost.

One pipeline, three surfaces, none bloating main:
- lessons: 503 docs -> translations branch, fetched at runtime with English
  fallback; English path byte-identical to before
- README: translated to the same branch, linked from the README header
- books: build_book.py --lang reads translated markdown and emits
  aiefs-vol{n}-{slug}-<lang>.epub/.pdf release assets (English fallback)

- languages.json: 40-language registry (FLORES-200 + ci flag) driving the
  script, the site switcher, and the CI matrix
- scripts/translate_lessons.py: prose-only walker keeps code/math/figures/
  tables/HTML/bold/links/metadata out of the model (byte-lossless across all
  503 lessons + README); per-language sha256 cache written per lesson so runs
  resume and never redo unchanged English; providers pluggable (nllb default)
- .github/workflows/translate.yml + translate-requirements.txt: one job per
  language, restores its cache, translates changed docs, pushes race-safe
- site switcher (40 languages, English fallback); build.js emits gitignored
  site/langs.js from the registry
- docs/i18n.md: architecture, no-waste guarantee, cost, quality sample
2026-08-01 12:53:35 +01:00