Back to Zeroclaw

Building the docs locally

docs/book/src/developing/building-docs.md

0.7.44.9 KB
Original Source

Building the docs locally

The docs site you're reading is published from docs/book/. You can build the same site on your own machine — useful for offline reading, previewing edits before opening a PR, or developing translations.

One-command quickstart

bash
cargo mdbook serve                       # serve all locales at http://localhost:3000/en/
cargo mdbook serve --locale ja           # live-reload against Japanese source
cargo mdbook build                       # static build of every locale into docs/book/book/
cargo mdbook refs                        # regenerate the auto-generated reference pages
cargo mdbook sync                        # after editing English source: re-extract + AI-fill delta
cargo mdbook sync --locale ja            # sync one locale only
cargo mdbook sync --force                # force-retranslate everything (quality pass)
cargo mdbook sync --locale ja --force    # force-retranslate one locale
cargo mdbook stats                       # show translated/fuzzy/untranslated per locale
cargo mdbook check                       # validate .po format (run before a translation PR)

Required tools

cargo mdbook will fail fast and tell you what's missing, but for reference:

ToolInstall
mdbookcargo install mdbook --locked
mdbook-i18n-helperscargo install mdbook-i18n-helpers --locked
cargohttps://rustup.rs
gettext (msgfmt, msgmerge)apt install gettext / brew install gettext

What gets built where

SourceOutputGenerated by
docs/book/src/**/*.md (hand-written)docs/book/book/<locale>/mdbook build
docs/book/src/reference/cli.md(same path; gitignored)cargo run -- markdown-help
docs/book/src/reference/config.md(same path; gitignored)cargo run -- markdown-schema
target/doc/ (rustdoc)docs/book/book/api/cargo doc --no-deps --workspace

The two reference/*.md files are generated from the actual clap derives and JSON schema in the code — never edit them by hand. Edit the /// doc comments on the relevant Rust types instead.

How translations stay current

English markdown is the only source maintained by humans. Translations are stored in docs/book/po/<locale>.po files, which act as a cache — not as copies of the docs.

When English source changes, cargo mdbook sync runs two stages:

  1. Extract: mdbook-xgettext regenerates po/messages.pot from the current English source
  2. Merge: msgmerge updates each locale's .po file — new strings get an empty msgstr ""; changed strings get marked #, fuzzy with the old translation preserved as a starting point

Then the command counts fuzzy + untranslated entries. If there's a delta and --provider is given, the fill-translations tool translates only those entries. Unchanged strings cost nothing — the .po file cache means re-running against unchanged source is a no-op.

Without --provider, cargo mdbook sync still runs extract + merge and reports how many strings need translation. Strings without a msgstr fall back to English at render time — partial translations are valid.

Adding a new locale

  1. Edit locales.toml at the repo root — the only file you need to touch:

    toml
    [[locale]]
    code = "xx"
    label = "Language Name"
    

    Everything else (lang-switcher.js, CI, cargo fluent fill, cargo mdbook sync) reads from this file automatically.

  2. Bootstrap and fill the docs translations:

    bash
    cargo mdbook sync --locale xx --provider ollama
    

    If the .po file doesn't exist it's bootstrapped automatically, then all entries are filled.

  3. Validate and preview:

    bash
    cargo mdbook check              # exits non-zero on format errors
    cargo mdbook stats              # show coverage counts
    cargo mdbook serve --locale xx
    

Release translation workflow

Before tagging a release, run a full translation pass locally and commit the updated .po files.

bash
# Fast delta pass (only new or changed strings since last release)
cargo mdbook sync --provider ollama

# OR: quality pass — re-translate everything
cargo mdbook sync --provider ollama --force

cargo mdbook check   # validate before committing
cargo mdbook stats   # review coverage

The model used is whatever is configured in [providers.models.<name>] in config.toml.

Tips

  • Fast iteration on prose: cargo mdbook serve auto-rebuilds on save. Skip cargo mdbook refs unless you've changed CLI flags or config schema.
  • Fast iteration on translations: edit po/<locale>.po and reload the browser — mdbook serve detects .po changes and rebuilds automatically.
  • Cleaning up: rm -rf docs/book/book target/doc removes everything generated.
  • Zero-cost re-runs: cargo mdbook sync against unchanged English source completes in seconds — no AI calls, no cost.