Files
siftlode/frontend/src/i18n/locales/en/feed.json
T
peter e90603d4db fix(feed): deep-review remediations for the filter-bar overhaul
Correctness / behaviour:
- Move the Personal Views modal from inside the collapsible filter rail to the
  feed page (moduleRegistry FeedPage), so opening it from the always-visible
  toolbar view chip works while the rail is unpinned (its default) instead of
  no-op'ing and latching modalOpen into a later stale pop-open.
- Migrate a persisted legacy global `tagMode` into per-category `tagModes` on the
  localStorage seed paths too (loadAccountFilters), matching the saved-view and
  URL paths — an upgrading user's topic any/all no longer silently reverts to 'or'.
- DateFilterSelect: reset the custom reveal on an external clear while the popover
  is closed (guard on !open, not maxAgeDays), so the trigger reverts to "Any time"
  instead of lingering on "Custom range" with empty fields.
- PersonalViewsModal delete: only advance the detail selection when the delete
  actually happened (remove() now resolves a boolean) — cancelling the confirm no
  longer switches the selected view.
- SavedViewsProvider: prefer the explicitly-applied (sticky) view among several
  that capture identical filters, so apply(B) isn't re-attributed to an earlier
  duplicate A (wrong "modified" chip name).

A11y:
- Give the clickable panel title a descriptive accessible name (titleActionLabel,
  wired to "Personal views") instead of announcing only "Filters".
- Give the "+N" overflow pill an aria-label ("N more filters").
- Use t("views.reorder") for the saved-view drag handle instead of a hardcoded
  English "reorder" literal.

Also extract the chip-fit decision into a pure, testable lib/chipOverflow.ts and
measure the inter-chip gap live (rem-safe) instead of a frozen 6px constant.
2026-08-22 06:33:48 +02:00

85 lines
3.1 KiB
JSON

{
"chips": {
"label": "Filtered by",
"remove": "Remove filter: {{name}}",
"contentNone": "No content types",
"count_one": "{{count}} filter",
"count_other": "{{count}} filters",
"moreCount_one": "{{count}} more filter",
"moreCount_other": "{{count}} more filters",
"maxAge_one": "Last {{count}} day",
"maxAge_other": "Last {{count}} days"
},
"loading": "Loading feed…",
"loadError": "Couldn't load the feed.",
"emptyTitle": "Your feed is empty",
"emptyBody": "Connect your YouTube account to import your subscriptions and build your feed.",
"setUp": "Set up my feed",
"browseShared": "Or just browse the shared library",
"demoEmptyTitle": "Nothing here in the demo",
"demoEmptyBody": "The demo account has no subscriptions of its own — but the whole shared library is yours to explore, filter and sort.",
"browseLibrary": "Browse the library",
"noMatches": "No videos match these filters.",
"channelScopeHint": "This channel isn't in your subscriptions feed — it may be hidden. Its videos are in the shared library.",
"viewInLibrary": "View in Library",
"videoCount_one": "{{formattedCount}} video",
"videoCount_other": "{{formattedCount}} videos",
"sortLabel": "Sort",
"viewLabel": "View",
"showLabel": "Watch state",
"contentLabel": "Content types",
"view": {
"cards": "Large cards",
"cardsSmall": "Small cards",
"rows": "Rows",
"rowsCompact": "Compact rows",
"tiles": "Tiles"
},
"dirAsc": "Ascending",
"dirDesc": "Descending",
"sortKey": {
"date": "Date",
"popular": "Popular",
"duration": "Duration",
"title": "Name",
"subscribers": "Channel subscribers",
"priority": "Channel priority",
"shuffle": "Surprise me",
"relevance": "Relevance"
},
"loadingMore": "Loading more…",
"hiddenNamed": "Hidden “{{title}}”",
"hidden": "Video hidden",
"undo": "Undo",
"markedWatchedNamed": "Marked watched “{{title}}”",
"markedWatched": "Marked watched",
"thisVideo": "this video",
"unwatch": "Unwatch",
"source": {
"label": "Source",
"tip": "Filter by how videos got here: your subscriptions/catalog only, plus videos you found via live YouTube search, or only those search results.",
"organic": "Hide search results",
"all": "Include search results",
"only": "Search results only",
"plex": "Plex"
},
"yt": {
"searchFor": "Search YouTube for “{{query}}”",
"resultsFor": "YouTube results for “{{query}}”",
"quotaNote": "Live results — uses shared API quota",
"freeNote": "Live results — no search quota used",
"back": "Back to feed",
"searching": "Searching YouTube…",
"noResults": "No YouTube videos found.",
"error": "YouTube search failed.",
"loadMore": "Load more (uses quota)",
"loadMoreFree": "Load more",
"show": "Show",
"ephemeralNote": "These results are temporary — they clear automatically unless you watch or save one.",
"clearNow": "Clear now",
"cleared_one": "Cleared {{count}} result",
"cleared_other": "Cleared {{count}} results",
"showHint": "How many results to fetch at a time — Load more pulls another batch of this size."
}
}