Skip to content

docs: German translation of the core guides, plus multilingual plumbing - #15627

Merged
Maffooch merged 6 commits into
DefectDojo:bugfixfrom
devGregA:devgrega/docs-i18n
Aug 14, 2026
Merged

docs: German translation of the core guides, plus multilingual plumbing#15627
Maffooch merged 6 commits into
DefectDojo:bugfixfrom
devGregA:devgrega/docs-i18n

Conversation

@devGregA

@devGregA devGregA commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Translates the 246 core guide pages (~257,000 words) into German, and adds the multilingual plumbing that every further language reuses. German is one language on purpose: it proves the whole pipeline end to end so the rest is repetition, not risk.

Layout choice

Translations sit beside their English source as <page>.de.md, not under a per-language contentDir. The contentDir approach would require moving every English page into content/en/, which breaks existing tooling and every open docs PR. English URLs are untouched: defaultContentLanguageInSubdir stays false, so English pages keep serving from the site root and German lands under /de/. Each translated page keeps the English slug, weight, aliases, and audience, so URLs, ordering, and the Open Source / Pro toggle behave identically in German.

Site chrome was the hidden half of this

The templates hardcoded their English text, so translating page bodies alone would have produced a German page with an English homepage, navigation, and footer. About sixty strings are now i18n lookups: nav labels, the homepage cards, the whole footer, the hero subtitle, and eleven screen-reader labels. Their terminology comes from the product UI catalogs (dojo/locale/<lang>/), so a severity or status word reads the same in the docs as it does in DefectDojo.

Two theme bugs fixed on the way

  • baseof.html now emits per-language lang and dir. The theme hardcoded the site-level language code and never emitted dir at all, so Arabic, Hebrew, Persian, and Urdu would have rendered left-to-right no matter how good the translation was.
  • Active-nav detection now strips the language prefix before comparing section segments. Without that, every item in a translated nav matched and rendered as the current page.

Scope

Translated: get_started (42), asset_modelling (41), admin (40), triage_findings (30), metrics_reports (21), automation (16), connectors (16), import_data (15), sensei (7), federal_compliance (7), navigation (6), help (3), issue_tracking (1), home.

Left English on purpose: releases/ changelogs (they churn with every release, and a stale translated changelog is worse than an English one) and supported_tools/ (219 pages of tables, scanner names, and CVE identifiers that are the same in any language). Nav entries for those sections point at the English URL, so nothing in a translated nav 404s.

Verification

  • Production build clean. English pages unchanged: 660 pages still build at the site root, and no English content file is modified by this branch (the diff is 246 new .de.md files, four new i18n/menu/docs files, and seven template or config edits).
  • All 246 pages passed the apply gates: fenced code blocks, shortcodes, link URLs, and heading structure identical to source, with the frontmatter whitelist enforced. Nothing partial is written for a page that fails.
  • 291 German pages build with zero {{< or {{% leakage in the rendered HTML (a broken shortcode renders literally, so this is the real test).
  • 0 of 246 pages identical to their English source; 88% carry German function words (the rest are short index pages that are mostly frontmatter).
  • Rendered locally: German nav, sidebar, TOC, title, and body all in German; active states correct in both languages.

A gate bug worth mentioning

Two long pages kept failing the fence gate on content that turned out to be correct. The gate paired code-fence markers with a regex anchored at column 0, so an indented or blockquoted opening fence ( ```yaml, > ```yaml) was skipped and that block's closing fence was mistaken for an opening one, which swallowed the following prose as "code" and hid its headings from the heading check. The gate now walks lines the way a markdown parser does. It is stricter than before, not looser: on one page it went from seeing 89 fenced blocks to all 98, and it now catches corruption inside blockquoted code that previously passed silently. Re-verified against eight deliberate mutations (translated code line, dropped fence, lost indentation, truncated body, demoted heading, rewritten URL) - all flagged, clean translations still pass.

Process

TRANSLATIONS.md documents the layout, what is and is not translated, how to add a language, and a quarterly refresh cadence. The refresh is incremental: --changed-since <ref> exports only pages whose English source moved, and any page whose English text is byte-identical carries its existing translation forward for free. That path is already proven here: this branch was resynced onto current bugfix mid-flight, and 64 of the 246 pages reused their earlier translation because their English had not changed.

Honest caveats

  • These are machine translations: integrity-checked, not meaning-checked. A native-speaker pass is the right next step before promoting a language heavily.
  • The remaining 26 languages' chrome strings are already translated and held outside the repo, so each additional language is its content run plus four files. A language is added to languages.toml only when its content lands, so the switcher never offers an empty language.
  • Trust Center and Status footer links from docs: link the Trust Center and Status page from the footer #15613 are not in this branch; whichever PR lands second should make those two labels i18n lookups as well.
  • One upstream page is named PRO__tagging_objects copy.md. It is draft: false and therefore live, so it is translated like any other page, but the filename looks accidental and is worth a separate cleanup.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Adds a German locale to the documentation site and the theme plumbing a
second language needs.

Content: 246 German pages covering the core guides (get started, import
data, triage, asset modelling, metrics, issue tracking, admin,
automation, connectors, federal compliance, sensei, help, navigation).
Changelogs and the supported_tools parser reference are out of scope for
this pass. Pages use the filename-suffix layout (page.de.md) so the
English tree stays where it is and open pull requests keep applying.

Theme: about 60 hardcoded English strings in the layouts move to i18n
lookups (navigation, homepage cards, hero, footer, aria labels), with
i18n/en.toml and i18n/de.toml holding them and a per-language menu file
for the sidebar. Two bugs surfaced while wiring this up and are fixed
here: baseof.html emitted a fixed lang attribute and no dir attribute,
and the header active-state check matched every navigation item once
URLs carried a language prefix.

Navigation entries for untranslated sections point at the English pages
so nothing 404s. TRANSLATIONS.md documents the layout, the scope, how to
add a language, and the quarterly refresh.

These are machine translations checked for structural integrity, not
reviewed for meaning. A native-speaker pass is recommended before
treating the German pages as authoritative.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@Maffooch Maffooch added this to the 3.2.200 milestone Aug 12, 2026
devGregA and others added 4 commits August 12, 2026 11:43
The German menu was generated from an older copy of menus.en.toml, so two
of its tabs pointed at pages that no longer exist and two tabs added
upstream were missing entirely. Because the menu renders on every page,
the two dead URLs became several hundred link-checker errors in CI.

Fixed against the current English menu: Model Your Assets now points at
the Assets page rather than a removed Organizations page, the top-level
Issue Tracking tab is gone (it is part of Connectors upstream), and the
Connectors and Sensei tabs are present. Added the Sensei chapter sidebar,
which uses pageRef so it resolves to the German pages by itself.

Hugo does not merge menus across languages and does not validate menu
URLs, so a per-language menu is an independent hand-maintained list that
nothing in the build checks. Verified here by resolving every menu URL
against the built site and by extracting every internal link from all
291 built German pages: zero unresolved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A translated page inherits the English page's aliases verbatim, and Hugo
treats a root-absolute alias literally. Both language versions then claim
the same path, one silently loses, and no language-prefixed alias page is
ever written. Relative links inside translated bodies do resolve to the
prefixed path, so every link that goes through an alias returned a 404 in
German while working in English. The Hugo build reports nothing; only the
link checker sees it.

Aliases on translated pages are now prefixed with the language, so the
German pages serve their own alias paths. 130 aliases across 148 pages.

Verified on a clean build with public/ removed first, since hugo leaves
stale files behind and those made the broken link resolve locally: every
internal link on all 1,121 built pages now resolves, and every menu URL
in both languages resolves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three more languages on the plumbing added for German, each covering the
same 246 core guide pages. Every page passed the integrity gates before
being written: code fences byte-identical to the English source,
shortcodes and link targets preserved, heading structure unchanged, and
the frontmatter whitelist enforced.

Each language ships its content, its i18n strings, and its own menu file.
The menu files are generated from the current menus.en.toml, so all four
languages carry the same set of tabs, and a tab whose page is not
translated points at the English URL rather than a missing page.

Verified on a clean build: 733 English pages plus 355 per language, no
shortcode leakage in any rendered page, every menu URL resolves in all
five languages, and every internal link across all 2,261 built pages
resolves. No page is identical to its English source; Japanese shows the
expected script coverage.

These are machine translations checked for structural integrity, not
reviewed for meaning. A native-speaker pass is recommended before
treating any of them as authoritative.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@devGregA
devGregA enabled auto-merge August 12, 2026 22:46
@devGregA
devGregA added this pull request to the merge queue Aug 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Aug 14, 2026
Resolve the footer.html conflict: DefectDojo#15613 added Trust Center and Status
links to the Company column while this branch converted the footer to
i18n lookups. Keep the i18n conversion and add both new links as i18n
lookups, reusing the footer_link_trust_center and footer_link_status
keys this branch already ships in all five locale files.
@Maffooch
Maffooch enabled auto-merge August 14, 2026 20:29
@Maffooch
Maffooch added this pull request to the merge queue Aug 14, 2026
Merged via the queue into DefectDojo:bugfix with commit 8eb67a8 Aug 14, 2026
48 checks passed
@Maffooch
Maffooch deleted the devgrega/docs-i18n branch August 14, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants