From 4c0cc5a7f5e198878db3904384c49084d4f70366 Mon Sep 17 00:00:00 2001 From: m105 Date: Wed, 22 Jul 2026 23:11:30 +0300 Subject: [PATCH] Add language filter to Discover The CDX languages field (ISO 639 codes, e.g. "spa,eng") has been captured on every page since the first ingestion command, but never surfaced anywhere. Filters via FIND_IN_SET for an exact code match rather than a LIKE substring match, since the column holds a comma-separated list. Verified against real data: lang=spa returns exactly the expected 47 sites (25+22 across two pages), a bogus code renders the empty state, and lang=spa combined with tld=es correctly narrows to 20. --- app/Livewire/Discover/Search.php | 23 +++++++++++++++++-- .../views/livewire/discover/search.blade.php | 8 ++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Discover/Search.php b/app/Livewire/Discover/Search.php index 8ee0f6e..3f50e60 100644 --- a/app/Livewire/Discover/Search.php +++ b/app/Livewire/Discover/Search.php @@ -14,7 +14,8 @@ use Livewire\WithPagination; * The competitor-discovery search: "who sells honey with a .es domain?" — keyword * matches a site's pages via MySQL fulltext (natural language mode, so free-text input * never trips a boolean-mode syntax error), TLD filters the site's domain suffix, - * platform filters its detected server/powered-by/generator signature. + * platform filters its detected server/powered-by/generator signature, language + * filters by the CDX-reported ISO 639 code of a page's content (e.g. "spa", "eng"). */ #[Layout('components.layouts.app')] class Search extends Component @@ -30,6 +31,9 @@ class Search extends Component #[Url(as: 'platform', history: true)] public string $platform = ''; + #[Url(as: 'lang', history: true)] + public string $language = ''; + public function updatingKeyword(): void { $this->resetPage(); @@ -45,12 +49,18 @@ class Search extends Component $this->resetPage(); } + public function updatingLanguage(): void + { + $this->resetPage(); + } + public function render(): View { $keyword = trim($this->keyword); $tld = strtolower(trim(ltrim($this->tld, '.'))); $platform = trim($this->platform); - $hasQuery = $keyword !== '' || $tld !== '' || $platform !== ''; + $language = strtolower(trim($this->language)); + $hasQuery = $keyword !== '' || $tld !== '' || $platform !== '' || $language !== ''; // Without any filter this would just be the full site list — that's what the // Sites page is for. Discover only returns results once you've asked it something. @@ -73,6 +83,15 @@ class Search extends Component ->orWhere('generator', 'like', '%'.$platform.'%'); }); }) + ->when( + $language !== '', + // languages is a comma-separated list of ISO 639 codes (e.g. "spa,eng") — + // FIND_IN_SET matches an exact code, not a LIKE substring match. + fn ($query) => $query->whereHas( + 'pages', + fn ($pageQuery) => $pageQuery->whereRaw('FIND_IN_SET(?, languages)', [$language]) + ) + ) ->withCount(['pages as matching_pages_count' => function ($pageQuery) use ($keyword) { if ($keyword !== '') { $pageQuery->whereFullText(['title', 'description', 'keywords', 'content'], $keyword); diff --git a/resources/views/livewire/discover/search.blade.php b/resources/views/livewire/discover/search.blade.php index ed9e1ac..dc961a5 100644 --- a/resources/views/livewire/discover/search.blade.php +++ b/resources/views/livewire/discover/search.blade.php @@ -23,6 +23,12 @@ placeholder="Platform, e.g. WordPress" class="w-full max-w-[14rem] rounded-md border border-neutral-300 px-3 py-2 text-sm focus:border-neutral-500 focus:outline-none dark:border-neutral-700 dark:bg-neutral-900" > +
@@ -53,7 +59,7 @@ @if ($hasQuery) No matching sites. @else - Enter a keyword, TLD, or platform to search. + Enter a keyword, TLD, platform, or language to search. @endif