diff --git a/api/video/discover.py b/api/video/discover.py index f068685d..5a3ae243 100644 --- a/api/video/discover.py +++ b/api/video/discover.py @@ -282,13 +282,19 @@ def register_routes(bp): if providers and "," in providers: providers = providers.replace(",", "|") # TMDB with_watch_providers OR-join sort = request.args.get("sort") or "popularity.desc" - lang = (request.args.get("lang") or "").strip() or None # explicit (foreign rail) + lang = (request.args.get("lang") or "").strip().lower() or None # explicit (foreign rail / browse) + # The Browse-all grid sends `lang=any` to opt OUT of the rail language preference + # entirely (ad-hoc search shows every language); a real code (en/ko/…) filters to it. + any_lang = lang in ("any", "all") + if any_lang: + lang = None hide_owned = (request.args.get("hide_owned") or "") in ("1", "true", "yes") # Preferred original-languages (multi) for GENERAL/curated rails — so the feeds # aren't flooded with foreign titles (e.g. Bollywood in Popular/Trending). A rail - # with an explicit `lang` (a dedicated foreign rail) bypasses this. Default 'en'. + # with an explicit `lang` (a dedicated foreign rail) or `lang=any` (browse) bypasses + # this. Default 'en'. prefer_langs = None - if not lang: + if not lang and not any_lang: try: from . import get_video_db raw = get_video_db().get_setting("discover_languages", "en") or "en" diff --git a/webui/index.html b/webui/index.html index 492e3ede..55707bb5 100644 --- a/webui/index.html +++ b/webui/index.html @@ -1072,6 +1072,7 @@
+
Browse the full catalog
@@ -1097,6 +1098,17 @@
+
+ + + + + + + + + +
diff --git a/webui/static/video/video-discover.js b/webui/static/video/video-discover.js index 9aba8ac6..e5ddfff3 100644 --- a/webui/static/video/video-discover.js +++ b/webui/static/video/video-discover.js @@ -23,7 +23,7 @@ io: null, hero: { items: [], idx: 0, timer: null }, cat: { title: '', q: '', page: 1, paginates: true, busy: false, hasMore: false }, - sel: { kind: 'movie', genre: '', decade: '', providers: '', sort: 'popularity.desc' }, // Browse panel + sel: { kind: 'movie', genre: '', decade: '', providers: '', lang: '', sort: 'popularity.desc' }, // Browse panel }; var AUTO = (typeof IntersectionObserver !== 'undefined'); // infinite-scroll capable var sentinelVisible = false; @@ -587,6 +587,10 @@ if (s.genre) { q.push('genre=' + s.genre); var gn = genreName(s.kind, s.genre); if (gn) bits.push(gn); } if (s.providers) { q.push('providers=' + s.providers); var pn = activeChipText('providers'); if (pn) bits.push('on ' + pn); } if (s.decade) { q.push('decade=' + s.decade); bits.push(s.decade + 's'); } + // Browse-all is a self-contained search: always send a language so it never silently + // inherits the rail language preference. 'any' = show every language; a code filters. + q.push('lang=' + (s.lang || 'any')); + if (s.lang) { var ln = activeChipText('lang'); if (ln) bits.push(ln); } openCategory(bits.join(' · '), q.join('&')); } function genreName(kind, id) { diff --git a/webui/static/video/video-side.css b/webui/static/video/video-side.css index 4be869b5..e3889fb1 100644 --- a/webui/static/video/video-side.css +++ b/webui/static/video/video-side.css @@ -2372,6 +2372,8 @@ body[data-side="video"] #soulsync-toggle { display: none; } color: rgba(255, 255, 255, 0.32); margin-right: 2px; } .vdsc-global .vdsc-toggle { margin-left: 0; } .vdsc-global .vdsc-langs { margin-left: 0; } +.vdsc-browse-label { font-size: 10.5px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; + color: rgba(255, 255, 255, 0.32); margin: 0 0 10px 2px; } /* ── 'Not interested' card button ──────────────────────────────────────────── */ .vsr-card { position: relative; }