> */ protected const TRANSLATED = [Page::class, Project::class, Call::class, Service::class]; public function key(): string { return 'stale-translations'; } public function permission(): ?string { return null; } public function run(): Finding { $count = 0; $samples = []; foreach (self::TRANSLATED as $model) { $records = $model::query() ->when($model === Call::class, fn (Builder $q) => $q->open()) ->unless($model === Call::class, fn (Builder $q) => $q->published()) // Loaded here rather than one record at a time: working this // out means reading the change history, and a check that costs // a query per record is one that gets switched off. ->with('revisions') ->get(); foreach ($records as $record) { $stale = TranslationFreshness::for($record); if ($stale === []) { continue; } $count++; // Which languages, and how long they have been drifting — // "since March" is what decides whether this is urgent. $samples[] = ContentTypes::title($record) .' ('.collect($stale) ->map(fn ($since, string $locale) => "{$locale}, ".$since->diffForHumans()) ->implode('; ').')'; } } return Finding::problem($this->key(), $count, samples: $samples); } }