Index: src/routes/changelog.js
===================================================================
--- src/routes/changelog.js	(revision bddbfe06df7504ffcb60b3afc363f30f43c7f7af)
+++ src/routes/changelog.js	(revision eb5f978375e885d17090a8dedb24802dda9a52b4)
@@ -2,5 +2,6 @@
  * Public changelog / release page.
  *
- * GET /changelog  -> renders CHANGELOG.md (the source of truth for releases).
+ * GET /changelog  -> renders the changelog in the visitor's language:
+ *   CHANGELOG.<lang>.md if a translation exists, else CHANGELOG.md (English base).
  */
 
@@ -11,18 +12,25 @@
 import { renderPage } from '../middleware/render.js';
 import { MarkdownService } from '../services/MarkdownService.js';
+import { resolveLang, t } from '../services/i18n.js';
+import { getSetting } from '../services/SettingsService.js';
 
 const router = express.Router();
 const __dirname = path.dirname(fileURLToPath(import.meta.url));
-const CHANGELOG_PATH = path.join(__dirname, '..', '..', 'CHANGELOG.md');
+const ROOT = path.join(__dirname, '..', '..');
 
 router.get('/changelog', (req, res) => {
-  let html;
-  try {
-    html = MarkdownService.render(fs.readFileSync(CHANGELOG_PATH, 'utf8'));
-  } catch {
-    html = '<p>Geen wijzigingenoverzicht beschikbaar.</p>';
+  const lang = resolveLang(req, {
+    userLang: req.session && req.session.user && req.session.user.lang,
+    defaultLang: getSetting('default_lang'),
+  });
+  // Visitor's language if a translation exists, else the English base.
+  const files = [path.join(ROOT, `CHANGELOG.${lang}.md`), path.join(ROOT, 'CHANGELOG.md')];
+  let html = '';
+  for (const f of files) {
+    try { html = MarkdownService.render(fs.readFileSync(f, 'utf8')); break; } catch { /* try next */ }
   }
+  if (!html) html = `<p>${t(lang, 'changelog.empty')}</p>`;
   renderPage(req, res, 'pages/changelog', {
-    pageTitle: 'Wijzigingen',
+    pageTitle: t(lang, 'changelog.title'),
     bodyClass: 'on-changelog',
     changelogHtml: html,
