The flat link rewriter and two-step flow
Read this page for screenshot URL layouts and the flat two-step asset flow. For cross-page markdown links and replace placeholders, see Documents — Link rewriting.
For docsOutput.style = "flat" (and unless rewriteRelativeLinks: false or a custom pathTemplate is set), a built-in rewriter runs before postProcessing. It handles cross-doc links (adding locale suffixes) and prepends a depth prefix to non-markdown asset URLs. Locale-specific asset paths (screenshots, /img/… bridges) are then rewritten by docsOutput.postProcessing.regexAdjustments.
Two-step flow when docsOutput.style = "flat"
- Source URL — image path in translated markdown (after segment reassembly)
- Flat link rewriter — prepends a depth prefix (
../,../../docs/, …) regexAdjustments— swaps the locale folder segment (en-GB→${translatedLocale})- Output URL — final path written to the translated file
Example with outputDir: "translated-docs/" and source README.md at repo root:
- Flat link rewriter:
images/screenshots/en-GB/foo.png→../images/screenshots/en-GB/foo.png(one../fortranslated-docs/) regexAdjustmentsruleimages/screenshots/[^/]+/→images/screenshots/${translatedLocale}/:../images/screenshots/de/foo.png
For any non-flat style (including "nested", "doc-system", and presets such as "docusaurus", "astro-starlight", and "vitepress"), the flat link rewriter does not run. regexAdjustments sees the original URL from the translated markdown (typically an absolute path like /img/screenshots/en-GB/foo.png).
Astro Starlight MDX: Starlight content is often .mdx. For those files, translate-docs runs postProcessing.regexAdjustments only — no flat, VitePress, Nextra, or Fumadocs link rewriter. Per-locale screenshot paths still use the same screenshots/[^/]+/ → screenshots/${translatedLocale}/ rule; see examples/astro-docs.
VitePress link normalizer (style: "vitepress")
When docsOutput.rewriteVitepressLinks is true (default when style is "vitepress"), a separate normalizer runs after segment reassembly (instead of the flat rewriter). It targets VitePress / doc-system sites where English lives at the content root and locales sit in sibling folders (docs/de/guide/…).
- Source href — link in translated markdown (after segment reassembly)
- VitePress link normalizer — rewrites doc paths to site routes (
/guide/…) regexAdjustments— optional locale-folder swap for screenshots (screenshots/en-GB/→screenshots/de/, …)- Output href — final URL written to the translated file
Typical rewrites:
| Source pattern | Normalized target |
|---|---|
docs/guide/foo.md | /guide/foo |
../guide/foo.md (from a locale file) | /guide/foo |
https://github.com/…/examples/console-app/ | unchanged (use full URLs for repo paths) |
For projects that sync README.md → docs/index.md, use full GitHub URLs in README.md for LICENSE, examples/, and other files outside the VitePress tree. See VitePress integration — README as the docs homepage.
The flat rewriter and VitePress normalizer are mutually exclusive per docs[] block — only one runs before regexAdjustments. See VitePress integration — Link conventions.
Per-locale screenshot folders still use the same screenshots/[^/]+/ → screenshots/${translatedLocale}/ regexAdjustments rule when needed; see Per-locale folder.
Nextra link normalizer (style: "nextra")
When docsOutput.rewriteNextraLinks is true (default when style is "nextra"), a separate normalizer runs after segment reassembly. It rewrites content/en/… and relative .mdx paths to locale-neutral routes (/guide/…). See Nextra integration — Link conventions.
Fumadocs link normalizer (style: "fumadocs")
When docsOutput.rewriteFumadocsLinks is true (default when style is "fumadocs"), a separate normalizer runs after segment reassembly. It rewrites content/docs/… and relative .mdx paths to locale-neutral routes (/docs/…). See Fumadocs integration — Link conventions.
Per-file depth prefix with flatPreserveRelativeDir
The depth prefix is computed per output file — not globally for the whole batch. For each source file, the rewriter computes the relative path from the output file's directory back to the source file's directory and uses that as the prefix.
This means that with flatPreserveRelativeDir: true, source files in subdirectories get the correct prefix automatically. For example, docs/guide/quick-start.md outputs to translated-docs/docs/guide/quick-start.<locale>.md. The per-file prefix is ../../docs/, so an asset translation-dashboard.png (a sibling of the source tree) becomes ../../docs/translation-dashboard.png — which resolves correctly from translated-docs/docs/guide/ back to docs/translation-dashboard.png.
No regexAdjustments correction is needed for relative-path assets alongside source files.
rewriteRelativeLinks and linkRewriteDocsRoot
| Option | Effect |
|---|---|
docsOutput.rewriteRelativeLinks | Explicitly enable or disable the flat link rewriter (overrides the default when docsOutput.style = "flat") |
docsOutput.linkRewriteDocsRoot | Root from which depthPrefix is computed (default ".") |
docsOutput.flatPreserveRelativeDir | Affects output path layout, which the rewriter uses when computing target paths for known translated files |
docsOutput.postProcessing.regexAdjustments
Configure ordered { "description"?, "search", "replace" } rules under docs[].docsOutput.postProcessing to rewrite image, screenshot, and other asset URLs that built-in rewriters do not handle — typically swapping a locale folder segment (screenshots/en-GB/ → screenshots/de/) or bridging absolute static paths (/img/… → ../assets/…).
Rules run on the translated markdown body after segment reassembly and built-in link rewriting (flat or VitePress), and before addFrontmatter. On flat layout, write search patterns against URLs after the depth prefix is applied — match the locale segment inside the path, not the leading ../.
Per-locale screenshot folders (flat layout):
"docsOutput": {
"style": "flat",
"postProcessing": {
"regexAdjustments": [
{
"description": "Per-locale screenshot folders",
"search": "images/screenshots/[^/]+/",
"replace": "images/screenshots/${translatedLocale}/"
}
]
}
}Use [^/]+ instead of hardcoding your source locale (en-GB) so the rule survives a sourceLocale change. The most common placeholder is ${translatedLocale}; ${sourceLocale}, ${sourceFilename}, ${translatedFilename}, and path variables are also available — see Documents — Link rewriting.
Layout-specific examples (flat, doc-system, Docusaurus, Starlight): Per-locale folder. General cross-page link rules: Documents — Link rewriting. Field reference: Configuration — docs.
See Common mistakes and troubleshooting for hardcoded locale regexes, missing screenshot directories, and Docusaurus /img/ bridging.