Request logging:
- One line per request from Flask hooks instead of the LoggingMiddleware.
It now also covers static files, unknown URLs, 500 errors and the
responses of the CSRF and auth middlewares. In debug mode, where Flask
skips after_request on exceptions, the status is logged as 500.
- All fields are logged as key=value.
- The session is logged as a short SHA-256 prefix instead of the raw id.
- In debug mode, the request lines of the Werkzeug dev server are
filtered out, since the app logs requests itself.
Translations:
- TranslationHandler keeps the language in flask.g instead of a class
attribute, so concurrent requests cannot overwrite each other's
language.
- Translating or rendering a template without a language raises
LanguageNotSet. Requests that do not pass the I18NMiddleware are
logged with lang=None.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
<meta charset="utf-8"> keeps the encoding when a page is saved locally.
<html lang> now uses the language of the request instead of a fixed
"en", which matters for screen readers, hyphenation and the browser's
translation prompt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
isort's lines_after_imports = 2 conflicted with black, so run-cleanup
reverted black's changes. Use isort's black profile instead and apply the
resulting formatting. Also fix the flake8 errors in check_email_mixin and
drop a leftover debug print.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>