siftlode/frontend/src/i18n/locales/en/plex.json

236 lines
7.2 KiB
JSON
Raw Normal View History

{
"navLabel": "Plex",
"backToFeed": "YouTube feed",
"backToLibrary": "Back to library",
"searchPlaceholder": "Search Plex…",
"sort": {
"added": "Recently added",
"title": "Title",
"year": "Year",
"rating": "IMDb rating",
"duration": "Length",
"release": "Release date"
},
"filter": {
"library": "Library",
feat(plex): unify movies + shows into one cross-library browser Collapse the separate Movie/Show library sections into ONE unified library with a shared search + shared filter sidebar and a Movies/Shows/Both scope selector. Backend: new GET /api/plex/library — a cross-library UNION of movies (plex_items) and shows (plex_shows) as one mixed, paginated, sorted feed, scoped movie|show|both, with the shared filters (extracted into _apply_meta_filters, DRY), FTS search, and per-user watch-state (a show's state = the aggregate of its episodes). On a search that also matches episodes, matching episodes come back in a separate 'episodes' list (the grouped 'Episodes' section — Proposal 3). /facets is now scope-aware (merged across the scope's libraries). /item and /show now return their library section key (for the admin collection editor, since there's no single library prop in the unified view). Frontend: PlexSidebar's library picker -> a scope selector (Both/Movies/Shows); facets + browse follow the scope (App's plexLib repurposed to a validated scope, default both). PlexBrowse uses the unified endpoint, renders a mixed Titles grid + an Episodes section on search. Poster cards are generalized: a hover Play/Resume overlay on every card, a clickable title (not just the poster), and a movie/show type tag. The quick watched toggle is now optimistic so it reliably flips BOTH ways (fixes the movie card that could mark but not un-mark). Cast/crew members and the show hero's meta (year/rating/genre/ content-rating) are clickable filters; clicking a person widens the scope to Both so the result is a mixed movie+show feed. i18n plex.filter.scope*/plex.unified.* (en/hu/de). Still pending from the polish list (next pass): season-card quick toggles (watched + add-to-playlist), per-episode watched toggle, and the full glassy art-bg + hide-cast customize menu on the series pages.
2026-07-11 00:15:49 +02:00
"scope": "Library",
"scopeOpt": {
"both": "All",
"movie": "Movies",
"show": "Shows"
},
"show": "Show",
"showOpt": {
"all": "All",
"unwatched": "Unwatched",
"in_progress": "In progress",
"watched": "Watched"
},
"sort": "Sort",
"clearAll": "Clear filters",
"active": "Active",
"any": "Any",
"rating": "IMDb rating",
"genre": "Genre",
"year": "Year",
"duration": "Length",
"durationOpt": {
"short": "Under 90m",
"mid": "90120m",
"long": "Over 2h"
},
"added": "Added to Plex",
"addedOpt": {
"24h": "24h",
"1w": "1 week",
"1m": "1 month",
"6m": "6 months",
"1y": "1 year"
},
"contentRating": "Age rating",
"match": {
"any": "Any",
"all": "All"
},
"dir": {
"desc": "↓ Descending",
"asc": "↑ Ascending"
},
"collection": "Collection",
"collectionSearch": "Search collections…",
"collectionEmpty": "No collections"
},
"count": "{{count}} titles",
"searchCount": "{{count}} matches",
"noMatches": "No matches.",
"noMatchesFiltered_one": "No matches — a filter is also narrowing the results.",
"noMatchesFiltered_other": "No matches — {{count}} filters are also narrowing the results.",
"loading": "Loading…",
"empty": "Nothing here yet. Run a Plex sync from the admin Config page.",
"loadMore": "Load more",
"watched": "Watched",
"inProgress": "In progress",
"play": "Play",
"resume": "Resume",
"openShow": "Open show",
"markWatched": "Mark watched",
"markUnwatched": "Mark unwatched",
"seasons": "{{count}} seasons",
feat(plex): unify movies + shows into one cross-library browser Collapse the separate Movie/Show library sections into ONE unified library with a shared search + shared filter sidebar and a Movies/Shows/Both scope selector. Backend: new GET /api/plex/library — a cross-library UNION of movies (plex_items) and shows (plex_shows) as one mixed, paginated, sorted feed, scoped movie|show|both, with the shared filters (extracted into _apply_meta_filters, DRY), FTS search, and per-user watch-state (a show's state = the aggregate of its episodes). On a search that also matches episodes, matching episodes come back in a separate 'episodes' list (the grouped 'Episodes' section — Proposal 3). /facets is now scope-aware (merged across the scope's libraries). /item and /show now return their library section key (for the admin collection editor, since there's no single library prop in the unified view). Frontend: PlexSidebar's library picker -> a scope selector (Both/Movies/Shows); facets + browse follow the scope (App's plexLib repurposed to a validated scope, default both). PlexBrowse uses the unified endpoint, renders a mixed Titles grid + an Episodes section on search. Poster cards are generalized: a hover Play/Resume overlay on every card, a clickable title (not just the poster), and a movie/show type tag. The quick watched toggle is now optimistic so it reliably flips BOTH ways (fixes the movie card that could mark but not un-mark). Cast/crew members and the show hero's meta (year/rating/genre/ content-rating) are clickable filters; clicking a person widens the scope to Both so the result is a mixed movie+show feed. i18n plex.filter.scope*/plex.unified.* (en/hu/de). Still pending from the polish list (next pass): season-card quick toggles (watched + add-to-playlist), per-episode watched toggle, and the full glassy art-bg + hide-cast customize menu on the series pages.
2026-07-11 00:15:49 +02:00
"unified": {
"titles": "Titles",
"episodes": "Episodes"
},
feat(plex): Plex-web-style 3-level series view (Phase 2 of series view) Restructure TV browsing into show detail → seasons → season episodes → player, like the Plex web app. Backend: /show/{rk} now returns a rich show page — hero meta (rating/content_rating/ genres/studio + live IMDb), live Cast & Crew, Related shows (Plex 'related', mapped to our mirrored shows so they're openable), and per-season cards with an aggregate watch-state + on-deck episode, plus show-level resume (on-deck)/first(play-from-start)/ status rollup. New PlexClient.related(). New bulk-state endpoints POST /show/{rk}/state and /season/{rk}/state mark every episode watched/unwatched for the user and mirror each change to a linked Plex account in the background (best-effort, checked once). Frontend: PlexShowView reworked into the show detail page (hero + Resume/Play-from-start/ Mark-show-watched/Add-to-playlist/[admin]Add-to-collection + season card grid + cast + related strips); new PlexSeasonView season subpage (hero + Resume/Play/Mark-season/ Add-season-to-playlist + landscape episode grid). Both read the one cached ['plex-show'] payload (season page picks its season out of it — instant, no extra fetch). Player queue = the whole show (from the show page) or the season (from the season page) so prev/next + auto-advance follow order. New 'season' history subview; Backspace steps back one drill level (grid←show←season, out of info/playlist) alongside browser/mouse Back. Season-level 'Add to collection' intentionally omitted (Plex collections hold whole shows, not seasons). i18n plex.series.* (en/hu/de).
2026-07-10 22:08:04 +02:00
"series": {
"seasons": "Seasons",
"backToShow": "Back to show",
"episodeCount": "{{count}} episodes",
"playFromStart": "Play from start",
"related": "Related shows",
"markShowWatched": "Mark show watched",
"markShowUnwatched": "Mark show unwatched",
"markSeasonWatched": "Mark season watched",
"markSeasonUnwatched": "Mark season unwatched",
"addShowCollection": "Add to collection"
},
"playerSoon": "Player coming soon — “{{title}}”",
"collEditor": {
"manage": "Collections",
"title": "Collections — {{title}}",
"newPlaceholder": "New collection name…",
"create": "Create",
"search": "Filter collections…",
"none": "No editable collections yet. Create one above.",
"count": "{{count}} items",
"delete": "Delete",
"deleteConfirm": "Delete the collection \"{{title}}\" from Plex? This affects all users.",
"note": "Changes are written to Plex and shared across all clients and users.",
"others": "Manage {{count}} existing collections…",
"makeEditable": "Manage"
},
"player": {
"loading": "Loading…",
"back": "Back",
"skipIntro": "Skip intro",
"skipCredits": "Skip credits",
"playPause": "Play / pause (space)",
"restart": "Restart from beginning",
"prev": "Previous episode",
"next": "Next episode",
"mute": "Mute (m)",
"fullscreen": "Fullscreen (f)",
"download": "Download original file",
"tracks": "Audio & subtitles",
"audio": "Audio",
"subtitles": "Subtitles",
"subOff": "Off",
"errNotFound": "This file can't be played — the media isn't reachable on the server (the Plex media mount is missing or the path map is wrong). Ask the admin to check the Plex configuration.",
"errTranscode": "This file's format needs transcoding, which isn't supported yet.",
"errGeneric": "Playback couldn't start. Please try again.",
"stop": "Stop",
"help": "Keyboard shortcuts",
"infoBtn": "Media info",
"keys": {
"playPause": "Play / pause",
"seek": "Seek 10 seconds",
"episode": "Previous / next episode",
"volume": "Volume up / down",
"mute": "Mute",
"fullscreen": "Fullscreen",
"info": "Media info",
"back": "Stop & back to feed",
feat(plex): rework player timing (copyts) + player settings & personalization Streaming / subtitle sync (the core fix): - stream.py: add -copyts so HLS segments carry the true absolute PTS, and measure the real keyframe start K from seg_0 (ffprobe) -> return it as the session start. Fixes the seconds-long subtitle lead caused by using the requested seek offset instead of the keyframe ffmpeg actually lands on with video stream-copy. - Add -noaccurate_seek so the re-encoded audio starts at the same keyframe as the video (was starting (X-K)s later -> seconds of silence after each seek/audio switch). - Compensate the fixed ~1.0s lag hls.js introduces for non-zero-start copyts streams, folded into the session start so the clock, seeking and the subtitle shift are all content-accurate. - /subtitle gains an offset param; _shift_vtt shifts absolute cues onto the session's zero-based clock and DROPS fully-past cue blocks (collapsing them to 0->0 made every past cue active at currentTime 0 on resume -> a pile-up until playback advanced). Audio: - /session + stream.py gain an audio A/V-sync offset (-itsoffset, full +/-, second input only when non-zero). Player settings & personalization (per-account, persisted -> survive F5): - storage.ts: useAccountPersistedObject (per-account JSON prefs blob). - PlexPlayer: volume/mute, audio+subtitle language (index-based match, fixes the F5 audio-revert), sync offsets, seek steps, subtitle style, auto-hide, play intent. - Hotkeys A (cycle audio) / S (cycle subtitle), mouse-wheel volume, Ctrl+arrow fine seek, per-user plain/fine seek-step + auto-hide toggle. - Subtitle appearance: size / colour / vertical position / background via ::cue + line. - UI: split into a Tracks quick-menu + a tabbed gear panel (Sync | Playback | Subtitle); both dismiss on outside-click; edge-aware control tooltips. - i18n en/hu/de for all new strings.
2026-07-08 21:35:38 +02:00
"help": "Show this help",
"audio": "Cycle audio track",
"subtitle": "Cycle subtitle",
"fineSeek": "Fine seek"
},
"settings": "Settings",
"sync": "Offsets",
feat(plex): rework player timing (copyts) + player settings & personalization Streaming / subtitle sync (the core fix): - stream.py: add -copyts so HLS segments carry the true absolute PTS, and measure the real keyframe start K from seg_0 (ffprobe) -> return it as the session start. Fixes the seconds-long subtitle lead caused by using the requested seek offset instead of the keyframe ffmpeg actually lands on with video stream-copy. - Add -noaccurate_seek so the re-encoded audio starts at the same keyframe as the video (was starting (X-K)s later -> seconds of silence after each seek/audio switch). - Compensate the fixed ~1.0s lag hls.js introduces for non-zero-start copyts streams, folded into the session start so the clock, seeking and the subtitle shift are all content-accurate. - /subtitle gains an offset param; _shift_vtt shifts absolute cues onto the session's zero-based clock and DROPS fully-past cue blocks (collapsing them to 0->0 made every past cue active at currentTime 0 on resume -> a pile-up until playback advanced). Audio: - /session + stream.py gain an audio A/V-sync offset (-itsoffset, full +/-, second input only when non-zero). Player settings & personalization (per-account, persisted -> survive F5): - storage.ts: useAccountPersistedObject (per-account JSON prefs blob). - PlexPlayer: volume/mute, audio+subtitle language (index-based match, fixes the F5 audio-revert), sync offsets, seek steps, subtitle style, auto-hide, play intent. - Hotkeys A (cycle audio) / S (cycle subtitle), mouse-wheel volume, Ctrl+arrow fine seek, per-user plain/fine seek-step + auto-hide toggle. - Subtitle appearance: size / colour / vertical position / background via ::cue + line. - UI: split into a Tracks quick-menu + a tabbed gear panel (Sync | Playback | Subtitle); both dismiss on outside-click; edge-aware control tooltips. - i18n en/hu/de for all new strings.
2026-07-08 21:35:38 +02:00
"subOffset": "Subtitle delay",
"audioOffset": "Audio delay",
"playback": "Playback",
"seekStep": "Seek step",
"fineSeek": "Fine seek (Ctrl)",
"autoHide": "Auto-hide controls",
"subStyle": "Subtitles",
feat(plex): rework player timing (copyts) + player settings & personalization Streaming / subtitle sync (the core fix): - stream.py: add -copyts so HLS segments carry the true absolute PTS, and measure the real keyframe start K from seg_0 (ffprobe) -> return it as the session start. Fixes the seconds-long subtitle lead caused by using the requested seek offset instead of the keyframe ffmpeg actually lands on with video stream-copy. - Add -noaccurate_seek so the re-encoded audio starts at the same keyframe as the video (was starting (X-K)s later -> seconds of silence after each seek/audio switch). - Compensate the fixed ~1.0s lag hls.js introduces for non-zero-start copyts streams, folded into the session start so the clock, seeking and the subtitle shift are all content-accurate. - /subtitle gains an offset param; _shift_vtt shifts absolute cues onto the session's zero-based clock and DROPS fully-past cue blocks (collapsing them to 0->0 made every past cue active at currentTime 0 on resume -> a pile-up until playback advanced). Audio: - /session + stream.py gain an audio A/V-sync offset (-itsoffset, full +/-, second input only when non-zero). Player settings & personalization (per-account, persisted -> survive F5): - storage.ts: useAccountPersistedObject (per-account JSON prefs blob). - PlexPlayer: volume/mute, audio+subtitle language (index-based match, fixes the F5 audio-revert), sync offsets, seek steps, subtitle style, auto-hide, play intent. - Hotkeys A (cycle audio) / S (cycle subtitle), mouse-wheel volume, Ctrl+arrow fine seek, per-user plain/fine seek-step + auto-hide toggle. - Subtitle appearance: size / colour / vertical position / background via ::cue + line. - UI: split into a Tracks quick-menu + a tabbed gear panel (Sync | Playback | Subtitle); both dismiss on outside-click; edge-aware control tooltips. - i18n en/hu/de for all new strings.
2026-07-08 21:35:38 +02:00
"subSize": "Text size",
"subPos": "Position",
"subColor": "Text color",
"subBg": "Background",
"subBgNone": "None",
"clock": "Clock",
"clockShow": "Show clock",
"clock24h": "24-hour",
"clockSize": "Size",
"clockColor": "Color",
"clockDate": "Show date",
"subShadow": "Shadow",
"subShadowColor": "Shadow color",
"autoSkipIntro": "Auto-skip intro",
"autoSkipCredits": "Auto-skip credits",
"autoSkipDelay": "Auto-skip delay"
},
"info": {
"title": "Media info",
"customize": "Customize view",
"prefArtBg": "Faint backdrop",
"prefCast": "Cast & crew",
"prefRelated": "Related shows",
"stripSource": {
"collection": "Collections",
"imdb": "IMDb",
"tmdb": "TMDb",
"tvdb": "TVDb",
"trakt": "Trakt",
"smart": "Smart lists"
},
"openImdb": "Open on IMDb",
"director": "Director",
"cast": "Cast & crew",
"markWatched": "Mark watched",
"markUnwatched": "Mark unwatched",
"clearResume": "Clear resume position",
"filterYear": "Show titles from {{year}}",
"filterRating": "Show titles rated {{n}}+",
"filterActor": "Show titles with {{name}}",
"browseCollection": "Browse collection →"
},
"playable": {
"direct": "Plays directly in the browser",
"remux": "Needs a light remux (no video re-encode)",
"transcode": "Needs transcoding (heavier)"
},
"playlistAdd": {
"manage": "Add to playlist",
"title": "Add to playlist — {{title}}",
"newPlaceholder": "New playlist name…",
"create": "Create",
"none": "No playlists yet. Create one above.",
"count": "{{count}} items",
"groupProgress": "{{in}} / {{size}}"
},
"playlist": {
"section": "Playlists",
"newPlaceholder": "New playlist…",
"create": "Create playlist",
"none": "No playlists yet.",
"deleteConfirm": "Delete the playlist \"{{title}}\"?",
"rename": "Rename",
"playAll": "Play all",
"delete": "Delete playlist",
"empty": "This playlist is empty. Add titles from their info page.",
"up": "Move up",
"down": "Move down",
"remove": "Remove",
"layoutAccordion": "Accordion view",
"layoutTree": "Tree view",
"removeShow": "Remove whole show",
"removeSeason": "Remove whole season",
"episodes": "{{count}} episodes",
"season": "Season {{n}}",
"seasonUnknown": "Episodes",
"addShow": "Add whole show to a playlist",
"addSeason": "Add season to a playlist",
"addEpisode": "Add episode to a playlist"
}
}