Round out referee amounts/colors, and add bilingual (nl/en) news content

Referee display: drop the redundant "External" pill from the PDF form, round
the event/dashboard "due" summary to 2 decimals (a fine-grained km rate like
0.083 was pushing the raw total to 3+ decimals), and theme the PDF's accent
colors off the club's own primary/secondary colors instead of a hardcoded
default.

News: title/body stay the club's own-language (Dutch) text; new optional
title_en/body_en carry a translation, with News.effective_title_en/
effective_body_en resolving the fallback to the original on read rather than
copying it in at save time -- so editing the Dutch text later never leaves a
stale English copy behind, and existing rows get correct fallback behaviour
with no backfill. The news form lays both languages out side by side; the
detail page only shows an English section when one was actually added. The
public API returns both languages in one call (title_nl/body_nl/excerpt_nl
alongside title_en/body_en/excerpt_en, the latter never blank) -- a breaking
rename of the previously-unprefixed title/body/excerpt fields.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 20:47:58 +02:00
parent 0a9ac67b21
commit 5dcffefb28
13 changed files with 265 additions and 31 deletions

View File

@@ -34,6 +34,10 @@ class News(ClubScopedModel):
"shown as plain text here in the control panel."
),
)
title_en = models.CharField(_("title (English)"), max_length=255, blank=True, help_text=_("Optional. Falls back to the title above when left blank."))
body_en = models.TextField(_("body (English)"), blank=True, help_text=_("Optional. Supports the same Markdown as the body above. Falls back to the body above when left blank."))
teams = models.ManyToManyField(Team, related_name="news_items", blank=True, verbose_name=_("teams"), help_text=_("Leave empty for club-wide news."))
visibility = models.CharField(_("visibility"), max_length=10, choices=Visibility.choices, default=Visibility.INTERNAL)
@@ -61,6 +65,19 @@ class News(ClubScopedModel):
self.status, self.published_at = self.Status.DRAFT, None
self.save(update_fields=["status", "published_at"])
@property
def effective_title_en(self) -> str:
"""The English title to show -- `title_en` when the editor set one,
else the Dutch `title`. Computed on read rather than copied into
`title_en` at save time, so editing the Dutch title later keeps this
current instead of leaving a stale English copy behind."""
return self.title_en or self.title
@property
def effective_body_en(self) -> str:
"""See `effective_title_en` -- same fallback, for the body."""
return self.body_en or self.body
@property
def is_scheduled(self):
"""PUBLISHED (past the editor's release gate) but its publish date hasn't