feat: i18n URL prefixes + German legal pages

All public-facing blueprints (public, planner, directory, content,
leads, suppliers) now serve under /<lang>/ (e.g. /en/, /de/). Internal
blueprints (auth, dashboard, admin, billing) are unchanged.

URL routing:
- Root / detects lang from cookie → Accept-Language → default 'en'
  and 301-redirects to /<lang>/
- Quart url_value_preprocessor pops <lang> into g.lang; url_defaults
  auto-injects it so existing url_for() calls need no changes
- Unsupported lang prefixes (e.g. /fr/) return 404
- Legacy bare URLs (/terms, /privacy, /imprint, /about, /features,
  /suppliers) redirect 301 to /en/ equivalents
- robots.txt and sitemap.xml moved to app-level root; sitemap now
  includes both en and de variants of every SEO page
- lang cookie persisted 1 year, SameSite=Lax

i18n:
- New i18n.py: SUPPORTED_LANGS, LANG_BLUEPRINTS, flat translation dicts
  for ~20 nav/footer keys in en + de
- lang and t injected into every template context

Templates:
- base.html: <html lang="{{ lang }}">, hreflang tags (en/de/x-default)
  on lang-prefixed pages, nav/footer strings translated via t.*, footer
  language toggle EN | DE, SVG racket logo removed from footer
- 6 legal templates (terms/privacy/imprint × en/de) replacing old 3:
  - English: GDPR sections with correct controller identity (Hendrik
    Dreesmann, Zum Offizierskasino 1, 26127 Oldenburg), real sub-
    processors (Umami self-hosted, Paddle, Resend with SCCs), German-
    law jurisdiction
  - German: DSGVO-konforme Datenschutzerklärung, AGB, Impressum per
    § 5 DDG; Kleinunternehmer § 19 UStG; LfD Niedersachsen reference

Tests updated to use /en/ prefixed routes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-20 02:28:59 +01:00
parent b19b6b907c
commit b416cd682a
18 changed files with 963 additions and 444 deletions

View File

@@ -7,6 +7,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
### Added
- i18n URL prefixes: all public-facing blueprints (`public`, `planner`, `directory`, `content`, `leads`, `suppliers`) now live under `/<lang>/` (e.g. `/en/`, `/de/`); internal blueprints (`auth`, `dashboard`, `admin`, `billing`) unchanged; root `/` detects language from cookie / Accept-Language header and 301-redirects; legacy URLs (`/terms`, `/privacy`, etc.) redirect to `/en/` equivalents
- German legal pages: full DSGVO-compliant `Datenschutzerklärung` (`/de/privacy`), `AGB` (`/de/terms`), and `Impressum` (`/de/imprint`) per § 5 DDG — populated with Hendrik Dreesmann's details, Kleinunternehmer § 19 UStG, Oldenburg address
- Rewritten English legal pages (`/en/terms`, `/en/privacy`, `/en/imprint`) with expanded GDPR sections, correct controller identity, proper data-processing details (Umami self-hosted, Paddle, Resend with SCCs), and German-law jurisdiction
- Language toggle (`EN | DE`) in footer; hreflang `en`, `de`, and `x-default` tags in `<head>` on all lang-prefixed pages
- `lang` cookie (1-year, SameSite=Lax) persisted on first visit; `lang` and `t` (translation dict) injected into every template context
- `i18n.py`: flat translation dicts for ~20 nav/footer keys in `en` and `de`; `LANG_BLUEPRINTS` and `SUPPORTED_LANGS` constants
- `sitemap.xml` and `robots.txt` moved to app-level root routes (not under `/<lang>`); sitemap now includes both language variants of every SEO page
- Cookie consent banner: fixed bottom bar with "Accept all" and "Manage preferences" (toggle for functional/A/B cookies); consent stored in `cookie_consent` cookie for 1 year; "Manage Cookies" link added to footer Legal section
### Changed