Making the i18n Layer Tell the Truth
Most of the last 48 hours went into the internationalisation layer, and none of it was glamorous. The locale switcher now generates its aria-label from the actual target locale instead of a hardcoded string. That's not a nice-to-have — a switcher that announces the wrong destination is a lie to a screen-reader user. We keyed the label to the locale it actually switches to and added an e2e test (locale-switcher.spec.ts) so it stays honest.
Blog routing got the same treatment. The post, list, and tag pages now filter by locale properly, backed by a new test in blog-locale-filter.test.ts. If a post doesn't exist in your language, the system should not pretend it does. Tests exist to prove the filter does what the code claims, not what we hope it does.
We also cleaned up navigation: Forum came out of the main nav and moved to a Community Forum link in the footer, across all four dictionaries. And the German dictionary copy got a spoken-register pass — grammar fixes and de-stiffening. Machine-flat German reads like a form letter. That's a bug in the copy, so we fixed it.