-
Notifications
You must be signed in to change notification settings - Fork 45
guides localize your docs
clean-jsdoc-theme can ship your documentation in multiple languages. Each
locale is rendered to its own static output — the default language at the root,
the others under /<locale> — and a language switcher in the header navigates
between them. Three kinds of content get translated:
| Content | Source | How |
|---|---|---|
| UI chrome (search, settings, nav labels) | a key→string catalog | translated in the locale JSON |
| API descriptions (class/member/param/return prose) | your doclets | translated in the locale JSON |
| Prose (home page, docs pages) | per-locale files |
README.<locale>.md + docs.<locale>/
|
The workflow runs through the clean-jsdoc CLI
(the aadesh package), backed by the pure i18n core
(bhasha).
Note
Prerequisites: JSDoc ≥ 4 (or TypeDoc, for extract) and Node ≥ 20. Install
the CLI alongside the theme:
pnpm add -D clean-jsdoc-theme @clean-jsdoc-theme/aadesh
The localization commands live under the clean-jsdoc i18n group; build stays
top-level (it renders your site with or without locales).
[!INFO] Localized builds are JSDoc-only today. The TypeDoc bridge can extract catalogs but does not yet render the per-locale sites — full multi-language output is on the JSDoc path.
Locales live in your existing jsdoc.json opts (TypeDoc: the cleanJsdocTheme
block) — there's no separate config file:
{
"opts": {
"destination": "dist",
"readme": "./README.md",
"docs": "docs",
"locales": [
{ "code": "en", "name": "English" },
{ "code": "ja", "name": "日本語" },
{ "code": "hi", "name": "हिन्दी" }
],
"defaultLocale": "en"
}
}A list of { code, name } (or bare "en" strings) plus the default. The name
is the switcher label, and codes are BCP-47-ish (en, pt-BR). defaultLocale
is optional — it defaults to the first locale in the list. A single-locale (or
no-locales) build is unaffected — it renders exactly as before.
clean-jsdoc i18n extractThis runs your pipeline, collects every translatable string (chrome + API), and
writes one committable catalog per locale under
clean-jsdoc-theme-artifacts/locales/:
clean-jsdoc-theme-artifacts/locales/
en.json # the skeleton — values ARE the source text
en.meta.json # auto-managed bookkeeping (don't edit)
ja.json # values blank until you translate them
ja.meta.json
...
Re-run i18n extract any time your docs change — it merges: new keys are added,
changed source marks a key stale, removed keys are soft-deleted (kept until
--prune). A no-change run produces a zero git diff.
Edit each locale's <code>.json by hand, or generate a prompt for an LLM:
clean-jsdoc i18n prompti18n prompt writes a ready-to-use prompt file per locale under
clean-jsdoc-theme-artifacts/locales/prompts/ — <code>.md for a small catalog,
or <code>.part-01.md, <code>.part-02.md, … chunked for context limits. Each
file contains only the untranslated and stale entries, with instructions to
preserve markdown, {@link}, code fences, and {var} interpolation tokens. The
CLI prints where the files landed:
ja: 60 entries → 2 prompt files:
clean-jsdoc-theme-artifacts/locales/prompts/ja.part-01.md
clean-jsdoc-theme-artifacts/locales/prompts/ja.part-02.md
Open each file and paste its contents into your LLM — or upload the .md
directly — then copy the returned translations back into the matching <code>.json
catalog. (The prompts directory is regenerated on every run and git-ignored, so
it never clutters your commits.)
You don't have to translate everything — anything left blank falls back to the default language, so a partially-translated site is fine (and the coverage shows up in the report).
clean-jsdoc i18n validate # warns on gaps, errors on malformations
clean-jsdoc i18n validate --strict # gaps become failures too (for CI)clean-jsdoc buildOne site per locale: the default locale at destination, each other locale under
destination/<locale>. The language switcher and hreflang alternates are wired
automatically from the set of locales each page actually exists in.
Serve the output over HTTP (not file://) — the full-text Pagefind index is
fetched at runtime and needs a real server:
pnpm dlx serve distDeploy the whole dist/ directory to any static host. The default locale sits at
the root and each other locale under its /<locale>/ prefix, so the switcher and
hreflang links resolve the same way in production as they do locally.
Catalogs cover the chrome and API reference. Free-form prose is localized by file — no extraction:
-
Home page — add a
README.<locale>.mdnext to your configured README (README.ja.md,README.hi.md, …). aadesh renders it as that locale's home; a missing variant falls back to the default README. -
Docs pages — add a sibling
docs.<locale>/directory next to youropts.docsfolder and translate the files you want. It overlays the default docs per file: a translated page wins, a missing one falls back to the default. So a locale only needs the pages it has actually translated.
README.md docs/ # default language
README.ja.md docs.ja/ # Japanese overlay (translate what you want)
README.hi.md docs.hi/ # Hindi overlay
Tip
Keep a doc's group frontmatter value the same across locales (translate the
title, not the group) — otherwise the same section can split into two
sidebar groups.
A translated heading rendered in a Latin display font can look wrong for CJK or
Devanagari. Override the font per locale with a <locale>: prefix in opts.fonts
— anything without a prefix is the default, and a locale that omits a slot falls
back to it:
{
"opts": {
"fonts": {
"heading": "Source Serif 4",
"body": "Roboto",
"ja:heading": "Noto Sans JP",
"ja:body": "Noto Sans JP",
"hi:heading": "Noto Sans Devanagari",
"hi:body": "Noto Sans Devanagari"
}
}
}Each locale's build then requests only its own families from Google Fonts.
Prefer a guided run? Invoke the CLI with no arguments:
clean-jsdocIt opens a welcome banner and a command picker — the i18n group (drilling into
extract / prompt / validate) and build — that prompts for each command's
options and offers to save the equivalent (namespaced) command to your
package.json scripts.
See examples/with-i18n-example
in the repo — a three-locale (en / ja / hi) project with translated API
descriptions, chrome, a per-locale home page, a localized Guide docs section
(with a deliberate fallback to show partial translation), and per-language fonts.
- aadesh Overview — the CLI in depth.
- bhasha Overview — the i18n core.
- Configuration — every theme option.
This wiki is auto-generated from docs-site/docs. Edit there — changes sync automatically. Full docs: https://ankdev.me/clean-jsdoc-theme/