docs/book/src/developing/building-docs.md
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.
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)
cargo mdbook will fail fast and tell you what's missing, but for reference:
| Tool | Install |
|---|---|
mdbook | cargo install mdbook --locked |
mdbook-i18n-helpers | cargo install mdbook-i18n-helpers --locked |
cargo | https://rustup.rs |
gettext (msgfmt, msgmerge) | apt install gettext / brew install gettext |
| Source | Output | Generated 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.
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:
mdbook-xgettext regenerates po/messages.pot from the current English sourcemsgmerge 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 pointThen 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.
Edit locales.toml at the repo root — the only file you need to touch:
[[locale]]
code = "xx"
label = "Language Name"
Everything else (lang-switcher.js, CI, cargo fluent fill, cargo mdbook sync) reads from this file automatically.
Bootstrap and fill the docs translations:
cargo mdbook sync --locale xx --provider ollama
If the .po file doesn't exist it's bootstrapped automatically, then all entries are filled.
Validate and preview:
cargo mdbook check # exits non-zero on format errors
cargo mdbook stats # show coverage counts
cargo mdbook serve --locale xx
Before tagging a release, run a full translation pass locally and commit the updated .po files.
# 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.
cargo mdbook serve auto-rebuilds on save. Skip cargo mdbook refs unless you've changed CLI flags or config schema.po/<locale>.po and reload the browser — mdbook serve detects .po changes and rebuilds automatically.rm -rf docs/book/book target/doc removes everything generated.cargo mdbook sync against unchanged English source completes in seconds — no AI calls, no cost.