Files
iptvnator/apps/web/src/assets/i18n/en.json
T
e45cd85a78 feat(settings): PIN-protected parental lock for categories (#285) (#1601)
* feat(settings): add PIN-protected parental lock for categories (#285)

Locks are per category (Xtream category ids, Stalker genre ids, M3U group
titles) and kept in one renderer lock store persisted to app_state /
localStorage; `categories.locked` is the SQLite index re-stamped from it.
While the lock is active the DB worker filters every content read, the PWA
data source, the Stalker store and the M3U channel list filter in memory,
and the enforcement service reloads the stores and steps off withheld
selections. Settings → Parental lock sets the PIN (PBKDF2, never in
Settings), the relock timeout and Lock now; lock toggles live in the
Xtream/M3U management dialogs and a new Stalker lock dialog, all behind
the PIN. Backups carry the locks per playlist entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): harden the parental lock after review

- The M3U group dialog opens only after the PIN, like the Xtream and Stalker
  dialogs: it lists locked group names and can rewrite the locks.
- Change PIN and Disable always verify the stored hash, even while the
  session is unlocked, so an app left unlocked cannot lose its lock.
- Stalker paging judges progress on the raw portal page: withheld ids the
  list has not seen count as progress, a page made only of locked rows
  requests the next one itself, and the VOD total is reduced by withheld
  ids so the grid stops asking once every visible row is in.
- Parental lock contract linked from the agent context map after the
  guidance reorganization; bridge helpers split out to stay under the
  file-size cap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): guard locked categories on routes, PWA search and paging

- Xtream and Stalker `:categoryId` routes carry a parental-lock guard: a
  locked category reached by URL prompts for the PIN and redirects to the
  section root on refusal (Electron row ids are mapped to provider ids).
- PWA search filters withheld categories like the catalog reads.
- Electron warm-cache detection confirms an empty, lock-filtered read with
  the unfiltered existence check instead of refetching from the provider.
- A Stalker lock flip past page 1 drops withheld rows at once and restarts
  the list from page 1 instead of appending onto stale pages.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): compile the PIN hashing helper in the Node backend build

The web backend compiles the shared interfaces library without DOM typings,
so the DOM-only `SubtleCrypto` / `BufferSource` names broke its Docker
build. The helper now describes the WebCrypto surface it needs structurally
and reaches it through `globalThis`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): close the remaining parental-lock gaps from review

- Detail routes check the item's own category: a locked movie or series
  paired with an unlocked category id in the URL is still refused.
- `requestUnlock()` awaits the settings load before it can answer "not
  active", so a slow startup cannot open a management dialog unguarded.
- `SETTINGS_UPDATE` only persists the `parentalLockEnabled` mirror and
  releases the worker on switch-off; it no longer re-locks the worker on
  every ordinary settings save under a renderer that shows "unlocked".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): cover PWA cold navigation, Stalker search and the PWA lock editor

- The Xtream detail guard hydrates the PWA session cache before judging an
  item on a cold navigation and fails closed when the catalog cannot place
  the item.
- The dedicated Stalker search route filters withheld genres, re-fires on
  lock changes, judges paging on the raw page and restarts from page 1 on a
  lock flip.
- The Xtream category dialog loads its lock candidates through the
  capability-selected data source; the PWA source now lists its raw
  categories with lock flags, so locks can be configured there too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): arm the relock timer on enable and harden Stalker search relock

- The idle timer follows the unlocked transition instead of `active`, so the
  session that just enabled the lock still locks itself later.
- Stalker search closes an open detail whose genre became withheld on
  relock and advances by itself past pages made only of locked rows (only
  while they add ids the list has not seen).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): close lock editors on relock and clear withheld details opened from All

The Xtream, Stalker and M3U category editors are gated by the PIN only when
they open; an idle relock left them on screen listing locked names with a
lock-rewriting Save. Each now closes itself when the session relocks.

ParentalLockEnforcementService also judges the selected Xtream/Stalker
item by its own category: a detail opened from All, recently added or
search has no selected category to vanish with, so it stayed open after a
relock.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): fail closed on unreadable settings and finish relock clean-up

- Unreadable settings (IndexedDB load failure) left the feature switch at
  its default and announced "unlocked" to the main process. A stored PIN
  now stands in for the switch, and without one nothing is announced, so
  the worker keeps its mirrored locked default.
- Lock applies run one at a time and abandon superseded results; the
  Electron data source keys its in-flight share by lock version so a
  relock can never reuse an unlock refresh's unfiltered rows.
- The stored in-portal Xtream search is re-run on a lock change.
- Stalker live/radio selections are judged by tv_genre_id, and both live
  layouts drop the playback of a channel whose category became withheld.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): fail closed on an unreadable lock store and make lock writes reliable

- A lock store that cannot be read is no longer treated as empty: while
  the lock is active every category is withheld (renderer predicates and
  set-based filters alike) until the PIN is entered or the store reads
  again, and writes are refused meanwhile so an empty in-memory store can
  never wipe the persisted locks. The lock set now lives in its own
  ParentalLockLockStore service.
- The M3U group dialog's lock write is awaited and a failed save is
  reported in a snackbar instead of being silently dropped.
- The Electron categories.locked re-stamp clears and re-locks inside one
  transaction, so a failed restamp keeps the previous index.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): drop pre-relock Stalker search pages and fail closed on a corrupt lock store

- A Stalker search page issued before a relock was filtered with the
  pre-relock withheld set and could still be applied after it; the
  staleness check now includes the parental lock version.
- A lock store payload that does not parse or is not an object is a
  failed read (everything withheld until it reads again), no longer an
  empty store.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): close the startup, re-stamp, relock-refresh and switch-persistence gaps

- The window before the initial lock store read settles now withholds
  everything, like an unreadable store: settings can report the feature as
  on before the locks are known.
- The store commits before the SQLite index re-stamp; a failed re-stamp
  now rolls the store back, a failed rollback re-stamps on the next
  access, and every launch re-derives the index from the store.
- Xtream category/content reloads fail closed: a rejected reload empties
  the affected lists (content types drop back to idle) instead of keeping
  rows read under the previous lock state.
- Enabling/disabling the feature persists through one guarded path that
  undoes the in-memory switch and skips the Electron mirror on a failed
  settings write.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(xtream): move the parental-lock reload specs beside the content spec

The content feature spec sits at the 1200-line spec cap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): await the startup lock-index reconciliation and withhold genre-less rows when failing closed

- The lock store is readable only once the SQLite index has been re-derived
  from it, and a re-stamp that keeps failing keeps the session fail-closed,
  so catalog reads can never serve rows stamped unlocked by a stale index.
- While everything is withheld, Stalker rows without a genre are withheld
  as well (the store filter and the renderer predicate).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): await the enablement mirror, restore partial lock stamps and validate nested lock-store entries

- The Electron mirror of the feature switch is awaited; a mirror that
  cannot be written undoes the settings write, so a reload never starts
  from a mirror that disagrees with the persisted switch.
- A failed multi-type re-stamp rolls the store back AND re-stamps every
  touched type from it, since earlier types may already carry the new
  locks; a failed rollback keeps the playlist stale (fail-closed).
- A persisted lock store whose nested entries are not what writeLocks
  produces is a failed read, not an empty store.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): withhold the Xtream catalog at relock time, keep exact M3U titles in backups, roll back a failed relock-timeout save

- A relock now fails closed immediately: the selected detail is stepped
  off against the lock store, the catalog lists and stored search results
  are emptied, and the filtered reloads publish only while the captured
  lock version is still current.
- Backups carry M3U lock titles verbatim (exact dedup), since the locks
  match group titles exactly.
- A relock-timeout write that fails reverts the in-memory value and shows
  the settings save-failure snackbar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): clear the lock index before a playlist's last lock leaves the store, retry failed PIN reads, guard backups on the lock store

- A write that removes a playlist's last lock clears the SQLite index
  first and drops the store key afterwards, so an interruption between the
  two can only leave a state the startup reconcile repairs toward locked.
- A PIN hash read failure is distinct from an absent PIN: the session stays
  locked and every PIN-protected step re-reads it first.
- Backup export awaits parental lock initialization and refuses to run
  while the lock store is not readable, since an absent lock field means
  "no opinion" on restore.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): withhold Electron Xtream reads while locks are unknown, persist the switch when settings are unreadable, re-stamp after a recovered read

- ElectronXtreamDataSource serves no categories, content or search hits
  while the lock store withholds everything; its SQLite index may still
  carry a stale stamp.
- setupPin decides whether to persist the switch from the settings value
  before the PIN is stored, since enabled follows hasPin while the switch
  is unknown.
- A lock store recovered by a later read marks its playlists stale so the
  index is re-derived, a persisted entry must carry all three lists, and a
  stale Stalker search page is dropped before touching the withheld-id
  bookkeeping.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): keep unlocked category routes reachable and defer a relock reload that overtakes the initial hydration

- The Xtream category guard no longer runs the item check on category-only
  routes (Number(null) is 0), which prompted for the PIN on every unlocked
  VOD and series category while the lock was active.
- A lock change during the initial Xtream hydration withholds the rows the
  hydration publishes and runs the filtered reload once it has settled,
  on every path that marks the content initialized.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): resolve hidden live categories before relocking playback and reload categories in the deferred hydration path

- The Xtream live layout resolves a playing channel's category through
  the unfiltered rows when the visible list lacks it (search can play a
  hidden category's channel); until that lookup lands the category is
  unknown and a relock stops the channel.
- A relock that overtakes the initial hydration now withholds the
  category publications too and reloads categories with the content.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): step off the M3U channel and Stalker selection before awaiting the Xtream relock reload

The Xtream store stays populated after leaving that portal, so its reload
runs on every apply; a locked M3U channel no longer keeps playing behind a
slow database or provider read.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): gate the workspace on parental lock init, edit only a readable lock store, guard the deferred reload, validate backup lock entries

- The workspace route resolver awaits ParentalLockService.initialize()
  next to the settings load, so no route or catalog activates before the
  PIN and lock store are known.
- Every lock write re-reads a failed store before building its edit, so a
  recovered store is edited rather than overwritten.
- The deferred hydration reload runs under the publish guard of the
  request that deferred it.
- Backup import validates every parental lock entry and rejects a damaged
  list instead of erasing the persisted locks on restore.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): discard stale hidden-category lookups and key withheld Stalker rows by their real identity

- A hidden-category lookup that lands after a later playback (same
  provider id, another playlist) no longer overwrites the newer channel's
  category; resolutions are generation- and playlist-checked.
- Withheld Stalker rows are keyed by id, stream_id, movie_id, series_id
  or the row's cmd/name, so id-less rows no longer collapse onto one key
  and stall paging past locked pages.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): gate the Electron cached category/content reads while locks are unknown

The warm-route hydration reads the cache directly; it now returns nothing
while the lock store withholds everything, like the live reads.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): retire in-flight searches on relock clearing and publish lock revisions after the stamps

- clearSearchResults() advances the search request version, so a search
  issued under the previous lock state cannot republish what a relock
  just cleared.
- A lock write publishes its store revision only once every touched type
  is stamped, so a reload triggered by it cannot read a later type
  through its old stamps.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): retire a resolving Stalker live playback when the session relocks

The embedded player defers selecting the channel until its stream
resolves, so the enforcement service's cleared selection could not retire
the request; it now carries the lock version it was issued under and is
dropped when a relock happened meanwhile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(settings): one lock entry point per rail plus a right-click Lock/Unlock

- Stalker's dedicated lock button becomes the same "Manage categories"
  (tune) button the Xtream rail has; it opens the lock-only dialog, so
  every portal type shares one entry point and the rail header keeps
  three actions.
- Right-clicking a category (Xtream, Stalker) or an M3U group offers a
  single-row Lock / Unlock through the shared CategoryLockMenuComponent,
  behind the same PIN gate and lock store as the dialog.
- The settings hint explains where locks are set; group lock strings added
  to all locales (ru/de translated).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(settings): serialize lock-store writes and drop a deleted playlist's locks

- Lock-store mutations run through one write queue: each rewrites the
  whole persisted store, so overlapping edits could otherwise snapshot
  the same store and the later write would drop the earlier edit.
- Deleting a playlist removes its locks through the PLAYLIST_DELETE_CLEANUP
  hook; "Remove all playlists" clears the lock store once the deletion
  has succeeded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): apply single-row lock toggles inside the lock store's write queue

The right-click Lock/Unlock (portal categories and M3U groups) built the
new list before entering the queue, so two quick toggles shared one
snapshot and the second dropped the first. Lock writes now accept an edit
of the current list, evaluated inside the queue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): retry a failed settings read before any parental-lock settings write

updateSettings writes the whole settings object, which after a failed
startup read is the defaults; enabling the lock or changing the relock
timeout then replaced the user's persisted preferences. The read is
retried first and the write refused while settings stay unreadable. The
settings writes move to parental-lock-settings-writer.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): show the locked-groups row on the M3U rail and roll the relock timeout back to the recovered value

- The M3U groups rail now renders the same "N locked · Enter PIN to show"
  row as the portal category rail, so locked groups no longer vanish
  without an in-context unlock.
- A failed relock-timeout write rolls back to the value read after the
  settings retry, not to the pre-retry default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): retry a failed clear-all of the lock store and keep restored new playlists free of stale locks

A lock-store clear that failed after "Remove all playlists" only logged,
so a later restore reusing a playlist id could inherit the deleted
playlist's locks. The in-memory store now empties at once and the
persisted clear is retried on the next access; a restore that creates a
playlist starts it from empty locks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): count radio playback as lock activity and read the lock store before a restore's stale-id check

- The idle relock no longer interrupts a playing radio station: playing
  <audio> counts as activity, like video.
- A restore retries a failed lock-store read before checking a reused id
  for stale locks, and aborts while the store stays unreadable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): drop withheld Stalker search rows at relock time and keep the M3U unlock row when every group is locked

- A relock during a page-1 Stalker search now filters the rows already on
  screen at once, so old unlocked results are not clickable while the
  replacement page is pending.
- When every M3U group is locked the groups rail still renders, with its
  "N locked · Enter PIN to show" row, instead of the plain empty state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(settings): keep the PIN dialog and the Stalker enforcement step off the initial path

Master (#1712) moved the UI component barrel and the Stalker data layer out
of main.js and tightened the initial budget to 2 MB. The parental-lock
prompt imported the PIN dialog through the ui/components barrel and the
enforcement service injected the Stalker store at startup, which pulled
both back in (2.55 MB, over budget). The PIN dialog now loads through a
local lazy file on the first prompt, and the Stalker step loads only while
a Stalker route is open: initial total 1.65 MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): restore the lock index when an emptying write fails and publish rollbacks after re-stamping

- Removing a playlist's last lock clears the SQLite index first; if the
  clear or the store write then fails, the index is re-stamped from the
  previous locks at once. Title matching and multi-source discovery query
  the worker directly and trust the index, so the stale flag alone did not
  protect them.
- A rollback publishes its store revision only after every type is
  re-stamped, so a reload cannot read a later type through the attempted
  stamps.
- docs: restore the index rules the earlier surfaces rewrite dropped from
  the contract, now in the Lock store lifetime section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): keep the M3U groups view when every group is locked

With every group locked the filtered channel list is empty, so the
container showed its generic empty state and the groups rail's
"N locked · Enter PIN to show" row never appeared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): fail closed when the lazy Stalker enforcement step cannot load

A rejected chunk (e.g. a stale PWA page after a deployment) escaped
applyStalker(), so a locked Stalker selection kept playing after a relock
and the Xtream step was skipped. The step now leaves the Stalker route on
a load failure, which clears the selection and stops playback, and the
Xtream step still runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): defer a stale Xtream hydration as soon as the catalog is withheld

On Electron a relock that overtook the initial content hydration waited
for the category reload before the content reload set the deferral flag;
the older unlocked hydration could publish its streams in that window.
withholdCatalog() now sets the flag itself, before anything is awaited.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): restore backup locks after the Xtream merge and snapshot the Stalker lock dialog's categories

- A backup restore now writes the parental locks last, so a failed Xtream
  merge leaves the playlist's previous locks in place instead of the
  backup's possibly smaller set.
- The Stalker lock dialog snapshots the category list before its lazy
  import and opens only if the route is unchanged, so another portal's
  categories can never be saved under this playlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): fail closed on relock ahead of the apply queue and judge Xtream selections by the lock store

- On relock the synchronous fail-closed steps (M3U channel, Stalker
  selection, the locked Xtream detail, catalog lists, stored search) run
  immediately instead of queueing behind an earlier apply that may still
  wait on a slow or hung read.
- The post-reload Xtream checks decide by the lock store through the
  unfiltered category rows rather than by absence from the reloaded list,
  which also omits merely hidden categories; unreadable rows fail closed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): require the PIN for lock-bearing backup restores and fail closed during index re-stamps

- A backup carrying lock lists replaces the matching playlists' locks,
  possibly with an emptier set; the import now asks for the PIN (after the
  file was chosen) and aborts when it is refused.
- While a write re-stamps the SQLite index the playlist counts as stale,
  so a relock inside that window reloads fail-closed instead of through
  the old stamps. The internal store write now needs only a readable
  store, so a rollback can still land.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): drop parental-lock Xtream reloads once the playlist is switched

A reload issued for playlist A no longer publishes into the shared Xtream
store after the user opened playlist B: the store's reloads guard on the
playlist they read for, and the enforcement apply retires its search
refresh and selection checks on a playlist switch as on a newer lock
version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): re-ask the PIN before a relocked backup merge and keep the PIN cooldown across prompts

A backup merge now asks for the PIN again right before it replaces a
playlist's locks when the app relocked during the import, instead of
relying on the answer given at the start. The wrong-PIN count and the
30-second pause move from the dialog into the lock service, so
dismissing and reopening the prompt no longer resets them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): refuse lock removals that commit after a relock and keep the index stale until the store write lands

Lock edits that take a lock away now commit only while the session is
unlocked, checked inside the write queue at commit time, so an editor
save still in flight (or queued) when the app relocks cannot remove
locks. Adding locks stays allowed. The Xtream category dialog drops its
lock draft after a relock, and a backup restore re-asks the PIN only
when it would remove a lock. Clearing a playlist's last lock keeps its
index stale until the store write has landed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): clear an Xtream detail from a hidden category synchronously on relock

The synchronous relock step now clears a selected Xtream item whose
category the visible category list cannot place (a manually hidden
category opened through search), instead of leaving it usable until the
awaited reloads and lookup finish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): fail closed when the Electron bridge lacks the parental lock worker filter

A new runtime capability requires the lock-state and index-stamping IPC.
When Electron reads Xtream through the SQLite worker without it (a
partial or older preload), the locked session withholds every category
instead of trusting a worker that never learned the lock state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): re-check lock removals at their durable commit points

A lock removal that passed the unlocked check before its write is asked
again right after the store write and, for Xtream, after the index
stamps. A relock in between writes the previous store back or rolls the
stamps back before anything is published. The stale-index bookkeeping,
index stamping and store merge move into helpers to keep the lock store
within the file size limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): retry a failed revert of a refused lock removal and fail closed meanwhile

When writing the previous store back after a relock-refused removal
fails, the lock store now keeps a pending rewrite, is not readable (the
locked session withholds everything) and rewrites the persisted store
from memory on the next access, so a restart cannot load the removal.
A failed "Remove all playlists" clear shares the same retry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): authorize lock removals when issued and close genre-less Stalker details in fail-closed mode

A lock removal is now authorized right before its first write is issued;
a relock that lands after that is ordered after the write, which
completes. This drops the post-write rollback, whose own failure could
leave the persisted store diverged from memory across a restart. The
Stalker search closes a detail without a genre on relock while every
category is withheld.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): restore the previous locks when an Xtream rollback write fails

When an Xtream lock edit's re-stamp fails and the rollback store write
fails too, memory now goes back to the previous locks and a pending
rewrite persists them on the next store access before the index is
re-stamped, so the failed edit cannot take effect through that re-stamp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(stalker): cover page-one rows leaving the screen on relock while the reload hangs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): offer the portal unlock row in fail-closed mode

When the lock store cannot be read every portal category is withheld
but no locked ids are known, so the rail showed no "Enter PIN to show"
row. It now shows the row without a count in that state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): fail closed for direct worker title lookups and capture the Stalker lock dialog context before the PIN

Catalog title matching and multi-source discovery query the SQLite
worker directly; they now return nothing while the parental lock
withholds everything (unreadable store or a bridge without the worker
filter). The Stalker lock dialog captures its playlist, provider and
section before the PIN prompt and re-checks them after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): retire multi-source alternatives on a lock change and keep reconcile off in-flight stamps

The VOD multi-source host keys its discovery session to the parental
lock version: a lock change drops the discovered sources, retires
discoveries and switches in flight, and rediscovers through the
worker's new lock state. Stale-index entries of a write still stamping
are no longer retried by a concurrent reconcile, which could re-stamp
from a store the write had not committed yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): fail closed on a rejected worker lock sync, tear down Stalker synchronously and capture the Xtream dialog context before the PIN

- A rejected lock-state sync to the SQLite worker makes the locked
  session withhold everything until a later sync succeeds.
- The Stalker enforcement chunk is preloaded when a Stalker route
  opens; a relock runs it synchronously, or leaves the route at once
  while it is not loaded, instead of awaiting the chunk.
- Xtream "Manage categories" captures playlist, provider and section
  before the PIN prompt and re-checks them after it and after the
  dialog import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): keep the relock timeout behind the PIN and bind M3U group lock toggles to their playlist

A locked session can no longer change the relock timeout: the Settings
selector is disabled until the PIN is entered and the service refuses
the change while locked. An M3U right-click lock toggle now captures its
playlist before the PIN prompt and is saved only if that playlist is
still open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): reset a locked M3U channel however it becomes active

The enforcement service now checks the active M3U channel whenever it
changes while locked, so numeric zapping, next/previous and remote
commands, which select from the full channel list, cannot start a
channel of a locked group. Numeric zapping also skips such a channel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): bind the M3U group management result to its playlist

The groups view captures the playlist before the PIN prompt and drops
the management dialog's hidden and locked group lists once another
playlist is open, so they cannot be saved under that playlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(parental-lock): record the accepted restart case of a failed rollback write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): build bulk lock drafts only from a readable lock store

The Xtream and M3U management dialogs offer lock toggles, and the
Stalker lock dialog opens, only once the lock store has been read. A
draft built from the empty fail-closed snapshot would otherwise replace
the real locks with nothing on Save if storage recovered in between.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): keep the parental lock switch on the saved state and roll back to the recovered value

The Settings switch snaps back to the saved state when clicked and
follows it once the PIN action succeeds, so a cancelled or refused PIN
no longer leaves it showing the opposite state. A failed switch write is
undone to the value read after the settings retry instead of the
hard-coded inverse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): match noncanonical PWA Xtream category ids against their locks

The PWA data source compared raw provider category ids such as "009"
with locks stored as numbers, so such a category stayed visible while
locked. Both sides are now compared in canonical numeric form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): close the M3U group editor on any relock

The group management dialog lists every group name, locked ones
included, even when it opened without lock toggles (unreadable lock
store). It now closes on any relock, and the groups view re-checks the
lock state before opening it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: 4gray <fourgray@proton.me>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-27 16:38:34 +02:00

1940 lines
110 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"CANCEL": "Cancel",
"CLEAR": "Clear",
"CLOSE": "Close",
"BACK": "Back",
"SHOW_MORE": "More",
"SHOW_LESS": "Less",
"PLAYLISTS": "Playlists",
"HOME": {
"TITLE": "IPTVnator",
"SUBTITLE": "Please select a playlist from the list or add a new playlist",
"TABS": {
"RECENTLY_ADDED": "Recently added playlists",
"FILE_UPLOAD": "Add via file upload",
"URL_UPLOAD": "Add via URL",
"TEXT_IMPORT": "Import from text",
"XTREME_IMPORT": "Add Xtreme Code",
"STALKER_PORTAL_IMPORT": "Add Stalker Portal"
},
"PLAYLISTS": {
"NO_PLAYLISTS": "No playlists were added",
"ADD_FIRST": "Please add your first playlist",
"WELCOME_TITLE": "Welcome to IPTVnator",
"WELCOME_DESCRIPTION": "Start your streaming journey by adding your first playlist. Connect to your favorite IPTV service and enjoy live TV, movies, and series.",
"ADD_YOUR_FIRST": "Add Your First Playlist",
"FEATURE_M3U": "M3U/M3U8 Files",
"FEATURE_XTREAM": "Xtream Codes",
"FEATURE_STALKER": "Stalker Portal",
"FEATURE_M3U_LABEL": "Add an M3U file or URL",
"FEATURE_XTREAM_LABEL": "Connect via Xtream Codes",
"FEATURE_STALKER_LABEL": "Connect to a Stalker portal",
"VALUE_PROPS_LABEL": "What you can do",
"VALUE_PROP_LIVE": "Live TV with EPG",
"VALUE_PROP_VOD": "Movies & Series",
"VALUE_PROP_MULTISOURCE": "Multi-source library",
"VALUE_PROP_OFFLINE": "Offline downloads",
"DASHBOARD_WELCOME_TAGLINE": "Your IPTV library, in one place.",
"DASHBOARD_WELCOME_DESCRIPTION": "Connect M3U files, Xtream Codes, or Stalker portals — then enjoy live TV, movies and series on every screen.",
"FEATURE_LIVE_TITLE": "Live TV",
"FEATURE_LIVE_DESC": "Stream live channels with full schedule.",
"FEATURE_VOD_TITLE": "Movies & Series",
"FEATURE_VOD_DESC": "On-demand library with covers and details.",
"FEATURE_EPG_TITLE": "EPG & Catch-up",
"FEATURE_EPG_DESC": "Program guide and time-shifted playback.",
"FEATURE_OFFLINE_TITLE": "Offline downloads",
"FEATURE_OFFLINE_DESC": "Save movies and episodes for later.",
"SOURCES_WELCOME_TITLE": "Add your first playlist",
"SOURCES_WELCOME_BODY": "Pick a source type below to get started.",
"SOURCE_M3U_NEEDS": "Local file or URL pointing to an M3U/M3U8 playlist.",
"SOURCE_M3U_ADD": "Add M3U",
"SOURCE_XTREAM_NEEDS": "Username, password and server URL from your provider.",
"SOURCE_XTREAM_ADD": "Add Xtream",
"SOURCE_STALKER_NEEDS": "Portal URL and MAC address (Ministra-compatible).",
"SOURCE_STALKER_ADD": "Add Stalker",
"CONTENT_LIVE": "Live",
"CONTENT_VOD": "Movies",
"CONTENT_SERIES": "Series",
"CONTENT_EPG": "EPG",
"NO_RESULTS_TITLE": "No playlists found",
"NO_RESULTS_DESCRIPTION": "No playlists match your search. Try adjusting your search terms or clear the filter to see all playlists.",
"ADDED_VIA_URL": "Added via URL upload. URL:",
"ADDED_VIA_FILE": "Added via file upload",
"XTREAM_PLAYLIST": "Xtream playlist",
"STALKER_PORTAL": "Stalker portal",
"CHANNELS": "Channels",
"ADDED": "Added",
"SHOW_DETAILS": "Show playlist details",
"REMOVE": "Remove playlist",
"SEARCH_PLAYLISTS": "Search playlists by title",
"INFO_DIALOG": {
"PLAYLIST_DETAILS": "Playlist details",
"TITLE": "Title",
"FROM_URL": "Added from the URL",
"IMPORT_DATE": "Import date",
"CHANNELS": "Number of channels",
"CLOSE": "Close",
"SAVE": "Save",
"USER_AGENT": "User agent",
"ORIGINAL_FILENAME": "Original filename",
"FILE_PATH": "File path",
"UPDATE_FAILED": "Last playlist update failed",
"AUTO_UPDATE": "Auto-update",
"AUTO_UPDATE_DESCRIPTION": "If the auto-refresh function is activated, the playlist will be updated automatically each time the app is started.",
"CUSTOM_USER_AGENT": "Some IPTV providers need a specific user-agent in order to play their playlist.",
"EXPORT_PLAYLIST": "Export playlist as m3u",
"SERVER_URL": "Server URL",
"USERNAME": "Username",
"PASSWORD": "Password",
"MAC_ADDRESS": "Mac Address",
"PLAYLIST_EXPORT_SUCCESS": "Playlist was exported successfully.",
"PLAYLIST_EXPORT_ERROR": "Error: Playlist export failed.",
"COPY_URL": "Copy URL to clipboard",
"URL_COPIED": "URL copied to clipboard"
},
"REMOVE_DIALOG": {
"TITLE": "Remove playlist",
"MESSAGE": "Are you sure you want to delete this playlist completely?",
"SUCCESS": "Playlist was removed successfully",
"IN_PROGRESS": "Removing playlist...",
"DELETING_FAVORITES": "Removing favorites...",
"DELETING_RECENT": "Removing recently viewed...",
"DELETING_PROGRESS": "Removing playback progress...",
"DELETING_DOWNLOADS": "Removing downloads...",
"DELETING_CONTENT": "Removing cached content...",
"DELETING_CATEGORIES": "Removing categories...",
"DELETING_PLAYLIST": "Removing playlist record..."
},
"UPDATED": "Updated",
"REFRESH": "Refresh playlist",
"REFRESH_XTREAM": "Refresh Xtream playlist from remote",
"REFRESH_XTREAM_DIALOG": {
"TITLE": "Refresh Xtream Playlist",
"MESSAGE": "This will delete the local Xtream cache and re-import categories and streams from the remote server. Favorites, recently viewed items, hidden category visibility, and playback progress are restored after a successful re-import when matching content still exists. If the server cannot be reached, the restore remains pending until a later successful refresh. Continue?",
"STARTED": "Refresh started. Navigating to playlist...",
"ERROR": "Failed to refresh playlist. Please try again.",
"IN_PROGRESS": "Refreshing playlist...",
"COLLECTING_DATA": "Collecting favorites and recently viewed...",
"DELETING_CONTENT": "Removing cached content...",
"DELETING_CATEGORIES": "Removing cached categories..."
},
"GLOBAL_FAVORITES": "Global favorites",
"GLOBAL_FAVORITES_DESCRIPTION": "Auto-generated playlist with aggregated favorites from all playlists",
"MY_PLAYLISTS": "My playlists",
"MY_PLAYLISTS_SUBTITLE": "all available playlists",
"PLAYLIST_UPDATE_SUCCESS": "Success! The playlist was successfully updated.",
"PLAYLIST_UPDATE_ERROR": "Error updating playlist details.",
"PLAYLIST_UPDATE_FILE_NOT_FOUND": "Playlist refresh failed. The local file is no longer available. Check the file path or re-import the playlist.",
"PLAYLIST_UPDATE_FILE_ACCESS_ERROR": "Playlist refresh failed. The app can no longer access the local file.",
"AUTO_REFRESH_UPDATE_SUCCESS": "Success! The playlists were successfully updated",
"AUTO_REFRESH_UPDATE_PARTIAL": "Playlist auto-refresh incomplete: {{updated}} of {{total}} playlists updated, {{failed}} failed.",
"AUTO_REFRESH_UPDATE_PARTIAL_WITH_SKIPPED": "Playlist auto-refresh incomplete: {{updated}} of {{total}} playlists updated, {{failed}} failed, {{skipped}} skipped (no URL or file path).",
"AUTO_REFRESH_UPDATE_FAILED": "Playlist auto-refresh failed. None of the {{total}} playlists could be updated.",
"AUTO_REFRESH_UPDATE_SKIPPED": "Playlist auto-refresh: {{updated}} of {{total}} playlists updated, {{skipped}} skipped (no URL or file path).",
"AUTO_REFRESH_ENABLED": "Auto-refresh enabled"
},
"ADD_PLAYLIST": {
"PICK_METHOD": "Pick how you want to connect. You can rename it later.",
"METHOD_URL_LABEL": "M3U URL",
"METHOD_URL_SUB": "Paste a link to a remote .m3u or .m3u8",
"METHOD_FILE_LABEL": "M3U file",
"METHOD_FILE_SUB": "Upload a playlist from your computer",
"METHOD_XTREAM_LABEL": "Xtream credentials",
"METHOD_XTREAM_SUB": "Connect with host, username and password",
"METHOD_STALKER_LABEL": "Stalker portal",
"METHOD_STALKER_SUB": "MAC address and portal URL",
"METHOD_TEXT_LABEL": "Raw m3u text",
"METHOD_TEXT_SUB": "For one-off lists or when you only have text",
"METHOD_AUTO_LABEL": "Auto-detect",
"METHOD_AUTO_SUB": "Paste the message from your provider"
},
"FILE_UPLOAD": {
"DRAG_DROP": "Drop an .m3u or .m3u8 file here",
"OR": "or",
"CHOOSE_PLAYLIST": "click to browse",
"BROWSE": "Browse files",
"REJECTED": "File was rejected, unsupported file format {{filename}}.",
"OPEN_FAILED": "Could not open \"{{filename}}\"."
},
"URL_UPLOAD": {
"PLAYLIST_URL": "Playlist URL (m3u, m3u8)",
"ADD_PLAYLIST": "Add playlist",
"CORS_NOTE": "Note: In order to avoid CORS issues at this point the application uses a public CORS Proxy service. If you want to upload a playlist with sensitive data, it's more secure to import it from a file.",
"ERROR_FETCH_FAILED": "Failed to fetch the playlist. Please check the URL and try again.",
"ERROR_403": "Access denied (403): The server refused the request. The URL may require authentication or the playlist is restricted.",
"ERROR_404": "Playlist not found (404): The URL does not point to a valid playlist. Please check the URL.",
"ERROR_401": "Unauthorized (401): Authentication is required to access this playlist.",
"ERROR_INVALID_TLS": "Certificate for this playlist host is invalid.",
"ERROR_TLS_HOST_UNKNOWN": "Could not determine the playlist host. Please retry manually.",
"TRUST_TLS_HOST": "Trust host",
"TRUST_TLS_HOST_TITLE": "Trust invalid certificate?",
"TRUST_TLS_HOST_WARNING": "Only continue if you trust this playlist host. IPTVnator will allow invalid TLS certificates for this host, but other hosts still require valid certificates."
},
"TEXT_IMPORT": {
"LABEL": "Insert m3u(8) playlist as text",
"BUTTON_LABEL": "Import"
},
"XTREAM_PLAYLIST": {
"TITLE": "Playlist title",
"SERVER_URL": "Server URL",
"USERNAME": "Username",
"PASSWORD": "Password",
"ADD": "Add",
"TEST_CREDENTIALS": "Test credentials",
"URL_VALIDATION_ERROR": "Should be a valid url with protocol (e.g. http://example.com or https://example.com:4324)",
"CONNECTION_TEST": {
"CREDENTIALS_REQUIRED": "Enter a username and password to test the connection.",
"TESTING": "Testing connection…",
"HTTP_CONNECTED": "Connected using HTTP. HTTPS is unavailable. The connection is not encrypted.",
"ACTIVE": "Connected. The portal is active.",
"INACTIVE": "The account is inactive or the credentials are incorrect.",
"EXPIRED": "The subscription has expired.",
"UNAVAILABLE": "The portal did not return valid account information.",
"HTTP_ERROR": "The server returned HTTP {{status}}.",
"TLS_ERROR": "Could not establish a secure connection. Check the server’s HTTPS configuration and certificate.",
"CONNECTION_ERROR": "Could not reach the server. Check its address and your network connection.",
"UNKNOWN_ERROR": "Could not test the connection.",
"TEST_PROTOCOLS": "Test HTTPS and HTTP",
"HTTP_PERMISSION": "This test may send your username and password over unencrypted HTTP if HTTPS is unavailable."
}
},
"STALKER_PORTAL": {
"TITLE": "Title",
"MAC_ADDRESS": "Mac Address",
"MAC_ADDRESS_HINT": "Format 00:1A:79:XX:XX:XX. Hyphens, dots and lowercase are corrected for you.",
"MAC_ADDRESS_OUI_HINT": "This address is outside Infomir's 00:1A:79 range. Most portals only accept that range and reject anything else without saying why.",
"MAC_ADDRESS_ERROR": "Enter a 12-digit MAC address, for example 00:1A:79:12:34:56.",
"SERIAL_NUMBER": "Serial Number (Optional)",
"SERIAL_NUMBER_HINT": "Use if already registered with provider",
"DEVICE_ID_1": "Device ID 1 (Optional)",
"DEVICE_ID_2": "Device ID 2 (Optional)",
"DEVICE_ID_HINT": "64 hex characters - use if provider requires specific device ID",
"DERIVE_DEVICE_IDS": "Generate device IDs from the MAC address",
"DERIVE_DEVICE_IDS_HINT": "Produces the same value as StbEmu (SHA-256 of the MAC). The portal locks on to the first device ID it receives and refuses every later one, so only turn this on for a MAC the portal has never seen, or one you already use with a StbEmu-generated ID.",
"DEVICE_ID_PINNED_WARNING": "The portal has already recorded a device ID for this MAC address. Changing or clearing it will lock this source out, because the portal only accepts the device ID it saw first.",
"SIGNATURE_1": "Signature 1 (Optional)",
"SIGNATURE_2": "Signature 2 (Optional)",
"SIGNATURE_HINT": "64 hex characters - use if provider requires device verification signatures",
"SERVER_URL": "Server URL",
"URL_HINT": "Enter a host or an address ending in /c, portal.php, or server/load.php.",
"URL_VALIDATION_ERROR": "Enter a valid http:// or https:// URL.",
"ADD": "Add",
"VALIDATING": "Validating portal...",
"CREDENTIALS_HINT": "Only needed when the portal asks for a login and password",
"AUTH_FAILED": "Failed to authenticate with the portal. Check the URL and MAC address.",
"EDIT_UNREACHABLE": "The portal did not respond. No changes were saved. Check the URL and try again.",
"LOGIN_REQUIRED": "This portal requires a login and password. Fill in the username and password fields and try again.",
"LOGIN_REJECTED": "The portal rejected the login and password.",
"PORTAL_REFUSED": "The portal refused access for this device.",
"DEVICE_CONFLICT": "The portal has a different device ID registered for this MAC address.",
"PORTAL_MESSAGE": "The portal reported: {{message}}"
},
"FILTER_BY_NAME": "Filter by name",
"FILTER_AND_SORT": "Filter & Sort",
"SORT_PLAYLISTS": "Sort playlists",
"SORT_OPTIONS": {
"NAME_ASC": "Name (A-Z)",
"NAME_DESC": "Name (Z-A)",
"NEWEST": "Date added (Newest first)",
"OLDEST": "Date added (Oldest first)",
"CUSTOM_ORDER": "Custom order (Drag & Drop)"
},
"PLAYLIST_TYPES": {
"M3U": "M3U (local, url, text)",
"XTREAM": "Xtream",
"STALKER": "Stalker"
},
"IMPORTED_AS_TEXT": "Imported as text",
"PARSING_ERROR": "Error: Parsing failed, not a valid playlist:",
"AUTO_DETECT": {
"LABEL": "Message from your provider",
"PLACEHOLDER": "Paste everything your provider sent — links, username and password, MAC address…",
"PRIVACY_HINT": "Detection runs locally in the app; nothing you paste is sent anywhere.",
"NO_MATCHES": "Nothing recognized yet. Paste the full message including the link or credentials.",
"CONFIDENCE_HIGH": "Confident match",
"CONFIDENCE_MEDIUM": "Likely match",
"CONFIDENCE_LOW": "Guess",
"USE": "Fill the form",
"M3U_TEXT_NOTE": "Looks like a raw M3U playlist — it will be imported as pasted text."
}
},
"SETTINGS": {
"PORTAL_CONNECTIONS": "Portal connections",
"PORTAL_CONNECTIVITY_GUARD": "Pause requests to unavailable portals",
"PORTAL_CONNECTIVITY_GUARD_DESCRIPTION": "After repeated connection failures, pause new Xtream and Stalker requests for 30 seconds. Try disabling this if a portal becomes unavailable intermittently. Applies after saving, without restarting.",
"PORTAL_CONNECTIVITY_GUARD_DISABLED": "Each request will run independently. Unavailable servers may take longer to report an error.",
"TITLE": "Settings",
"SEARCH_RESULTS_TITLE": "Search results",
"SEARCH_RESULTS_COUNT": "Settings matching “{{query}}”: {{count}}",
"SEARCH_EMPTY_HINT": "No settings match. Try another word, such as player, theme or EPG.",
"GENERAL": "General",
"GENERAL_SUBTITLE": "Change the configuration of the application",
"PLAYBACK": "Playback",
"EPG_SOURCES": "EPG sources",
"EPG_SOURCES_DESCRIPTION": "Add one or more XMLTV sources: remote links or local files",
"PLAYLIST_EPG_SOURCES_AUTO_SELECTED": "{{enabled}} of {{detected}} detected playlist EPG sources were auto-selected for import.",
"EPG_EMPTY_TITLE": "No EPG sources yet",
"EPG_EMPTY_HINT": "Add a URL or a local XMLTV file to fetch program data for your channels.",
"PREFER_UPLOADED_EPG_TITLE": "Prefer your EPG sources for Xtream playlists",
"PREFER_UPLOADED_EPG_HINT": "By default, Xtream playlists use the program guide from your provider, and your uploaded EPG only fills missing channels. Turn this on to use your uploaded EPG first instead.",
"DATA": "Data",
"BACKUP": "Backup",
"BACKUP_DESCRIPTION": "Export your library as a snapshot, or restore from a previous backup.",
"RESET": "Reset",
"RESET_DESCRIPTION": "Permanently delete content stored in this app.",
"ABOUT": "About",
"NAV_GENERAL": "General",
"NAV_PLAYBACK": "Playback",
"NAV_EPG": "EPG",
"NAV_REMOTE": "Remote",
"NAV_DATA": "Data",
"NAV_BACKUP": "Backup",
"NAV_RESET": "Reset",
"NAV_ABOUT": "About",
"NAV_TMDB": "Metadata",
"TMDB": "Metadata (TMDB)",
"TMDB_DESCRIPTION": "Enrich movie and series details with data from The Movie Database",
"TMDB_ENABLE": "Enable TMDB metadata",
"TMDB_ENABLE_DESCRIPTION": "Improves plots, cast, ratings and artwork in detail views. When enabled, movie and series titles are sent to TMDB.",
"TMDB_API_KEY": "TMDB API key (optional)",
"TMDB_API_KEY_DESCRIPTION": "Use your own TMDB API key instead of the built-in one",
"TMDB_GET_KEY_HINT": "Get a free API key on themoviedb.org",
"TMDB_M3U_VOD_DETAILS": "Recognize movies in M3U playlists",
"TMDB_M3U_VOD_DETAILS_DESCRIPTION": "Playlist entries that look like movie files open in the movie detail view with TMDB metadata instead of the program guide panel.",
"TMDB_TEST_BUTTON": "Check key",
"TMDB_TEST_SUCCESS": "The key works — TMDB responded successfully",
"TMDB_TEST_FAILED": "Check failed — TMDB rejected the key or is unreachable",
"TMDB_CACHE": "Metadata cache",
"TMDB_CACHE_DESCRIPTION": "Downloaded metadata is stored locally so detail pages open instantly. Clearing it makes the app fetch fresh data on the next visit.",
"TMDB_CACHE_SIZE": "{{entries}} entries · {{size}}",
"TMDB_CACHE_CLEAR": "Clear cache",
"TMDB_CACHE_ERROR": "Could not read the cache — try again",
"TMDB_CREDITS": "Metadata",
"TMDB_ATTRIBUTION": "This product uses the TMDB API but is not endorsed or certified by TMDB.",
"APP_PREFERENCES": "App preferences",
"HERO_EYEBROW": "Workspace settings",
"HERO_TITLE": "Shape how IPTVnator feels",
"HERO_DESCRIPTION": "Tune playback, guides, remote access and data handling from one place without losing the current workspace style.",
"SUBTITLE": "Change the configuration of the application",
"DESCRIPTION": "Please adapt the options from the list below and confirm with the save changes button",
"EPG_URL_LABEL": "EPG source (URL or local file, *.xml or *.xml.gz)",
"EPG_URL_PLACEHOLDER": "Enter a URL or a local file path",
"REFRESH_EPG": "Refresh EPG",
"REFRESH_ALL_EPG": "Refresh all",
"REMOVE_EPG_SOURCE": "Remove EPG source",
"BROWSE_EPG_FILE": "Choose a local XMLTV file…",
"EPG_STATUS_FRESH": "Up to date",
"EPG_STATUS_STALE": "Needs refresh",
"EPG_STATUS_ERROR": "Failed",
"VIDEO_PLAYER_LABEL": "Video player",
"PLAYER_HTML5": "HTML5 video player",
"PLAYER_VIDEOJS": "Video.js player",
"PLAYER_ARTPLAYER": "ArtPlayer",
"PLAYER_EMBEDDED_MPV": "Embedded MPV (Experimental)",
"PLAYER_MPV": "MPV player",
"PLAYER_VLC": "VLC",
"VIDEO_PLAYER_PLACEHOLDER": "Select an option",
"VERSION": "Version",
"SAVE_CHANGES": "Save changes",
"UNSAVED_CHANGES": "You have unsaved changes",
"DISCARD_CHANGES": "Discard",
"UNSAVED_DIALOG_TITLE": "Unsaved changes",
"UNSAVED_DIALOG_MESSAGE": "You have unsaved settings changes. Do you want to save them before leaving?",
"UNSAVED_DIALOG_SAVE": "Save and leave",
"UNSAVED_DIALOG_DISCARD": "Leave without saving",
"UNSAVED_DIALOG_STAY": "Keep editing",
"UNSAVED_DIALOG_INVALID_HINT": "Some fields are invalid, so the changes cannot be saved yet.",
"BACK_TO_HOME": "Back",
"NEW_VERSION_AVAILABLE": "There is a new version available",
"LATEST_VERSION": "You are using the latest version",
"STREAM_FORMAT": "Stream Format",
"OPEN_EXTERNAL_PLAYER_ON_DOUBLE_CLICK": "Start MPV/VLC with double-click",
"OPEN_EXTERNAL_PLAYER_ON_DOUBLE_CLICK_DESCRIPTION": "Require a double-click on channel rows before MPV or VLC playback starts.",
"LANGUAGE": "Language",
"SETTINGS_SAVED": "Success! Configuration was saved.",
"SETTINGS_SAVE_FAILED": "Settings could not be saved. Your changes will be lost when the app is restarted.",
"SETTINGS_LOAD_FAILED": "Saved settings could not be loaded — showing defaults. Make sure no other copy of the app is running.",
"THEME": "Visual theme",
"SHOW_CAPTIONS": "Show subtitles",
"SHOW_DASHBOARD": "Show dashboard",
"SHOW_DASHBOARD_DESCRIPTION": "Keep Dashboard available in the workspace rail. When disabled, Sources becomes the first workspace page.",
"ADD_EPG_SOURCE": "Add EPG source",
"CLEAR_EPG_DATA": "Clear EPG data",
"CLEAR_EPG_DIALOG": {
"TITLE": "Clear EPG data",
"MESSAGE": "Are you sure you want to remove all EPG (Electronic Program Guide) data from the database? This will delete all cached program schedules."
},
"EPG_DATA_CLEARED": "EPG data has been cleared",
"EPG_DATA_CLEAR_FAILED": "Failed to clear EPG data. Please try again.",
"CLEARING_EPG_DATA": "Clearing…",
"EPG_URL_ERROR": "Enter an http(s) link, an absolute file path or a file:// URL",
"EPG_SOURCE_LIST_TITLE": "Source list",
"EPG_SOURCE_FORMATS_HINT": "Remote XMLTV links (http/https) and files on this computer are both supported, as plain .xml or gzip-compressed .xml.gz. Local files need an absolute path or a file:// URL.",
"EPG_SOURCE_FORMATS_EXAMPLES": "Examples:",
"VIDEO_PLAYER_DESCRIPTION": "Select default video player",
"WEB_PLAYER_SHARED_CONTROLS": "Unified controls for web players",
"WEB_PLAYER_SHARED_CONTROLS_DESCRIPTION": "Use IPTVnator's shared controls in HTML5, Video.js, and ArtPlayer.",
"PLAYER_AMBIENT_MODE": "Ambient background fill",
"PLAYER_AMBIENT_MODE_DESCRIPTION": "Fill the space around the player with a blurred, dimmed poster instead of plain black bars.",
"PLAYER_UP_NEXT_RAIL": "Up Next episode rail",
"PLAYER_UP_NEXT_RAIL_DESCRIPTION": "On wide windows, dock the series player to the left and show the upcoming episodes beside it.",
"FULLSCREEN_CHANNEL_PANEL": "Channel and episode list in fullscreen",
"FULLSCREEN_CHANNEL_PANEL_DESCRIPTION": "Rest the mouse on the left edge, click it, or press C while in fullscreen to slide in the channel list of a live stream or the episode list of a series and switch without leaving fullscreen.",
"STREAM_FORMAT_DESCRIPTION": "Auto prefers HLS. If live playback fails in MPV, VLC or Embedded MPV, stop the player, select ts, save and reopen the channel. Web players can try advertised TS once after an initial HLS HTTP failure.",
"LANGUAGE_DESCRIPTION": "Select language of the application",
"THEME_DESCRIPTION": "Select visual theme of the application",
"COVER_SIZE": "Cover size",
"COVER_SIZE_DESCRIPTION": "Adjust the size of poster cards across grids and rails. Larger sizes are easier to see on TVs; smaller sizes show more content per row on big monitors.",
"COVER_SIZE_SMALL": "Small",
"COVER_SIZE_MEDIUM": "Medium",
"COVER_SIZE_LARGE": "Large",
"COVER_TITLES": "Show titles under covers",
"COVER_TITLES_DESCRIPTION": "Turn off for a posters-only wall in movie and series grids: the title appears on the cover when you point at it or focus it. Live channels, search results and dashboard rails keep their labels.",
"EPG_VIEW_MODE": "Guide view",
"EPG_OFFSET_TITLE": "EPG time offset",
"EPG_OFFSET_HINT": "Shift displayed programme times without refreshing the guide. Use minutes, from -720 to 720.",
"EPG_OFFSET_LABEL": "Offset (minutes)",
"EPG_OFFSET_ERROR": "Enter a whole number of minutes between -720 and 720.",
"EPG_VIEW_MODE_DESCRIPTION": "Choose how the programme guide under the player is shown: a horizontal timeline ribbon or a vertical, single-day list.",
"EPG_VIEW_MODE_TIMELINE": "Timeline",
"EPG_VIEW_MODE_LIST": "List",
"STARTUP_BEHAVIOR": "Startup view",
"STARTUP_BEHAVIOR_DESCRIPTION": "Choose whether IPTVnator opens the first available workspace view or restores your last section-level view. First view means Dashboard when enabled, otherwise Sources.",
"STARTUP_BEHAVIOR_FIRST_VIEW": "First available view",
"STARTUP_BEHAVIOR_RESTORE_LAST_VIEW": "Restore last view",
"STARTUP_WINDOW_MODE": "Window on startup",
"STARTUP_WINDOW_MODE_DESCRIPTION": "Choose how the desktop window opens: at its last size, maximized, or fullscreen. Applies on the next launch. Press F11 at any time to enter or leave fullscreen.",
"STARTUP_WINDOW_MODE_NORMAL": "Last window size",
"STARTUP_WINDOW_MODE_MAXIMIZED": "Maximized",
"STARTUP_WINDOW_MODE_FULLSCREEN": "Fullscreen",
"SHOW_CAPTIONS_DESCRIPTION": "Show or hide subtitles by default",
"SHOW_EXTERNAL_PLAYBACK_BAR": "Show now playing footer",
"SHOW_EXTERNAL_PLAYBACK_BAR_DESCRIPTION": "Keep the external-player status bar visible at the bottom of the workspace on desktop.",
"STRIP_COUNTRY_PREFIX": "Strip country prefixes from channel names",
"STRIP_COUNTRY_PREFIX_DESCRIPTION": "Removes country/group prefixes like \"US | \" or \"UK - \" from live channel names throughout the app.",
"VERSION_DESCRIPTION": "Current version of the application",
"ABOUT_SUBTITLE": "Version, project links and ways to support IPTVnator.",
"EMBEDDED_MPV_NOTICE_TITLE": "Embedded MPV runtime",
"EMBEDDED_MPV_NOTICE_DESCRIPTION": "Desktop builds can include bundled libmpv and FFmpeg libraries for the experimental Embedded MPV player. Users do not need to install the MPV app separately; external MPV and VLC remain available as fallback players.",
"COMMUNITY": "Project & community",
"COMMUNITY_DESCRIPTION": "Star the repository, read the blog or join the Telegram group for updates and help.",
"LINK_BLOG": "Blog",
"LINK_GITHUB_DESCRIPTION": "Star the repo, open an issue or contribute",
"LINK_BLOG_DESCRIPTION": "Release notes, tips and project updates",
"LINK_TELEGRAM_DESCRIPTION": "Announcements, community and support",
"SUPPORT_TITLE": "Support the project",
"SUPPORT_DESCRIPTION": "IPTVnator is free and open source, built in the open. If it is part of your daily routine, a small contribution helps keep the project alive and shape what comes next — thank you.",
"SUPPORT_SPONSORS_HINT": "Recurring or one-time",
"SUPPORT_KOFI_HINT": "Buy me a coffee",
"EPG_NOTE": "Currently EPG is available only in the electron-based version of IPTVnator.",
"EPG_NOTE_URL_TEXT": "Check it here",
"IMPORT_EXPORT_DATA": "Import/export playlist backups",
"IMPORT_EXPORT_DATA_DESCRIPTION": "Export or restore playlist backups including M3U snapshots, Xtream/Stalker connection metadata, user state, and EPG source URLs.",
"IMPORT_DATA": "Import",
"EXPORT_DATA": "Export",
"EXPORTING_DATA": "Exporting…",
"REMOVE_ALL": "Delete all playlists and playlist data",
"REMOVE_ALL_BUTTON": "Delete all",
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
"REMOVE_DIALOG": {
"TITLE": "Delete all playlists?",
"MESSAGE": "Delete all {{count}} playlists from the app. This also removes stored playlist data on this device.",
"SUMMARY_TITLE": "Playlist sources",
"CONSEQUENCES_TITLE": "This also removes",
"CONSEQUENCE_FAVORITES": "Favorites saved for these playlists",
"CONSEQUENCE_RECENTLY_VIEWED": "Recently viewed history",
"CONSEQUENCE_PLAYBACK": "Saved playback positions",
"CONSEQUENCE_DOWNLOADS": "Download history entries linked to those playlists",
"CONSEQUENCE_XTREAM_CACHE": "Imported Xtream categories and locally cached content",
"BACKUP_HINT": "Use Export first if you want a restorable backup before deleting.",
"CONFIRM": "Delete everything"
},
"IMPORT_ERROR": "Import error, please try with another file.",
"PLAYLISTS_REMOVED": "All playlists and playlist data were removed.",
"MPV_PLAYER_PATH_LABEL": "mpv path",
"MPV_PLAYER_PATH_DESCRIPTION": "Set the path to MPV. On macOS you can use the MPV app bundle, such as /Applications/mpv.app, or the executable path.",
"MPV_COMPATIBLE_PLAYER_TIP": "IINA can be launched as an MPV-compatible player on macOS, but use its executable path, such as /Applications/IINA.app/Contents/MacOS/iina-cli or /Applications/IINA.app/Contents/MacOS/IINA. IPTVnator controls, position polling, and reuse-instance behavior are guaranteed only for MPV IPC.",
"MPV_PLAYER_PATH": "mpv player path",
"MPV_PLAYER_ARGUMENTS_LABEL": "mpv command-line arguments",
"MPV_PLAYER_ARGUMENTS_DESCRIPTION": "Optional arguments passed to mpv when IPTVnator starts a new external player process.",
"MPV_PLAYER_ARGUMENTS": "mpv arguments",
"MPV_REUSE_INSTANCE_LABEL": "Reuse MPV instance",
"MPV_REUSE_INSTANCE_DESCRIPTION": "When enabled, the same MPV window will be reused for playing different streams. When disabled, each stream opens in a new MPV window.",
"RECORDING_FOLDER_LABEL": "Recording folder",
"RECORDING_FOLDER_DESCRIPTION": "Folder for live stream recordings from Embedded MPV. Leave empty to use the system Downloads folder.",
"RECORDING_FOLDER": "Recording folder",
"RECORDING_FOLDER_SELECT": "Select recording folder",
"VLC_PLAYER_PATH_LABEL": "VLC path",
"VLC_PLAYER_PATH_DESCRIPTION": "Set the path to VLC. On macOS you can use the VLC app bundle, such as /Applications/VLC.app, or the executable path.",
"VLC_PLAYER_PATH": "VLC player path",
"VLC_PLAYER_ARGUMENTS_LABEL": "VLC command-line arguments",
"VLC_PLAYER_ARGUMENTS_DESCRIPTION": "Optional arguments passed to VLC when IPTVnator starts a new external player process.",
"VLC_PLAYER_ARGUMENTS": "VLC arguments",
"EXTERNAL_PLAYER_ARGUMENTS_HINT": "Use one argument per line. These values are applied before stream-specific IPTVnator options.",
"VLC_REUSE_INSTANCE_LABEL": "Reuse VLC instance",
"VLC_REUSE_INSTANCE_DESCRIPTION": "When enabled, the same VLC window will be reused for playing different streams. When disabled, each stream opens in a new VLC window.",
"REMOTE_CONTROL": "Remote control",
"REMOTE_CONTROL_DESCRIPTION": "Enable remote control of the application.",
"REMOTE_CONTROL_PORT": "Remote control port",
"REMOTE_CONTROL_PORT_DESCRIPTION": "Port used for remote control of the application. Port 8765 is used by default.",
"REMOTE_CONTROL_URL": "Remote control URL",
"REMOTE_CONTROL_URL_DESCRIPTION": "Access the remote control from another device on the same network.",
"SHOW_QR_CODE": "Show QR code",
"STATUS_ENABLED": "Enabled",
"STATUS_DISABLED": "Disabled",
"SOURCE_SINGULAR": "source",
"SOURCE_PLURAL": "sources",
"PORT_RANGE_LABEL": "Port (1-65535)",
"PORT_REQUIRED": "Port is required",
"PORT_MIN": "Port must be at least 1",
"PORT_MAX": "Port must be at most 65535",
"PORT_PATTERN": "Only digits are allowed",
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
"NAV_DASHBOARD": "Dashboard",
"DASHBOARD": "Dashboard",
"DASHBOARD_SUBTITLE": "Choose which dashboard rails are shown in the workspace.",
"DASHBOARD_HERO": "Hero banner",
"DASHBOARD_HERO_DESCRIPTION": "Show the large top banner for your most recent item.",
"DASHBOARD_RAIL_CONTINUE": "Continue Watching",
"DASHBOARD_RAIL_CONTINUE_DESCRIPTION": "Show recently watched movies and series as cover cards.",
"DASHBOARD_RAIL_LIVE_FAVORITES": "Live now on your favorites",
"DASHBOARD_RAIL_LIVE_FAVORITES_DESCRIPTION": "Show favorite live channels with current EPG progress.",
"DASHBOARD_RAIL_RECENT_LIVE": "Recently watched live TV",
"DASHBOARD_RAIL_RECENT_LIVE_DESCRIPTION": "Show live channels you opened recently with current EPG progress.",
"DASHBOARD_RAIL_FAVORITE_VOD": "Favorite movies & series",
"DASHBOARD_RAIL_FAVORITE_VOD_DESCRIPTION": "Show favorited movies and series as cover cards.",
"DASHBOARD_RAIL_SOURCES": "Recently used sources",
"DASHBOARD_RAIL_SOURCES_DESCRIPTION": "Show shortcuts to your most recently used playlists and portals.",
"DASHBOARD_RAIL_TMDB_TRENDING": "Trending this week (TMDB)",
"DASHBOARD_RAIL_TMDB_TRENDING_DESCRIPTION": "Show weekly trending movies and series from TMDB, matched against your libraries. Requires TMDB metadata to be enabled.",
"DASHBOARD_RAIL_TMDB_RECOMMENDATIONS": "Recommended for you (TMDB)",
"DASHBOARD_RAIL_TMDB_RECOMMENDATIONS_DESCRIPTION": "Show recommendations based on your recently watched movies and series, matched against your libraries. Requires TMDB metadata to be enabled.",
"DASHBOARD_RAIL_XTREAM_ADDED": "Recently added on Xtream",
"DASHBOARD_RAIL_XTREAM_ADDED_DESCRIPTION": "Show the newest Xtream movies, series, and channels.",
"APP_UPDATE_TITLE": "Application update",
"APP_UPDATE_DESCRIPTION": "Check GitHub Releases for desktop app updates.",
"APP_UPDATE_IDLE": "Ready to check for updates",
"APP_UPDATE_CHECKING": "Checking for updates…",
"APP_UPDATE_AVAILABLE": "Version {{version}} is available",
"APP_UPDATE_NOT_AVAILABLE": "You are using the latest version",
"APP_UPDATE_DOWNLOADING": "Downloading version {{version}}…",
"APP_UPDATE_DOWNLOADED": "Version {{version}} is ready to install",
"APP_UPDATE_MANUAL_AVAILABLE": "Version {{version}} is available for manual installation",
"APP_UPDATE_ERROR": "Update check failed",
"APP_UPDATE_CHECK": "Check again",
"APP_UPDATE_DOWNLOAD": "Update",
"APP_UPDATE_INSTALL": "Restart application",
"APP_UPDATE_OPEN_RELEASE": "Open GitHub release",
"APP_UPDATE_RELEASE_NOTES": "What's new",
"APP_UPDATE_RELEASE_NOTES_NOT_FOUND": "No release notes were found for {{version}} on GitHub. The release may have been removed or is not published yet.",
"APP_UPDATE_RELEASE_NOTES_LOAD_FAILED": "Release notes could not be loaded.",
"APP_UPDATE_OPEN_RELEASES_PAGE": "Open releases page",
"APP_UPDATE_CHANNEL": "Update channel",
"APP_UPDATE_CHANNEL_DESCRIPTION": "Stable follows the tagged releases. Nightly follows every merge into master and installs prerelease builds automatically. Applies on Save.",
"APP_UPDATE_CHANNEL_STABLE": "Stable",
"APP_UPDATE_CHANNEL_NIGHTLY": "Nightly",
"APP_UPDATE_SAVE_AND_CHECK": "Save and check for {{channel}} updates",
"APP_UPDATE_CHANNEL_PENDING_HINT": "This result is for the {{current}} channel. Save to switch to {{next}} and check again.",
"APP_UPDATE_CHANNEL_RETAINED_HINT": "This update was found on the {{current}} channel. The {{next}} channel has not been checked yet.",
"APP_UPDATE_CHANNEL_NIGHTLY_WARNING": "Nightly builds are untested snapshots of master. They may break, and their database changes are permanent: switching back to Stable keeps this build until the next stable release is newer. Back up your playlists first.",
"APP_UPDATE_NIGHTLY_ON_STABLE_HINT": "You are running a nightly build. The Stable channel will offer the next stable release once it is newer than this build.",
"EMBEDDED_MPV_FRAME_COPY": "Embedded MPV: frame-copy engine (experimental)",
"EMBEDDED_MPV_FRAME_COPY_DESCRIPTION": "Render video onto the app canvas so menus and dialogs stack above it.",
"EMBEDDED_MPV_FRAME_COPY_RESTART": "Takes effect after restarting the app.",
"EMBEDDED_MPV_EXTRA_OPTIONS": "Extra embedded MPV options",
"EMBEDDED_MPV_EXTRA_OPTIONS_DESCRIPTION": "Advanced libmpv options for the embedded player, one key=value pair per line (no leading --). They apply on every engine after the built-in options and take effect when the next embedded MPV session starts.",
"EMBEDDED_MPV_EXTRA_OPTIONS_HINT": "Example: hwdec=auto-safe. Options the embed itself depends on (wid, vo, input-ipc-server, …) are refused.",
"EMBEDDED_MPV_EXTRA_OPTIONS_INVALID_LINES": "Not a key=value line: {{lines}}",
"EMBEDDED_MPV_EXTRA_OPTIONS_FORBIDDEN_KEYS": "These options cannot be changed for the embedded player: {{keys}}",
"EMBEDDED_MPV_AUTO_RECONNECT": "Reconnect dropped streams automatically",
"EMBEDDED_MPV_AUTO_RECONNECT_DESCRIPTION": "When a playing stream drops, the embedded player reloads it with increasing delays, up to 6 attempts, before giving up. A stream that never started still needs a manual Retry.",
"VOD_AUTO_FAILOVER": "Auto-switch source on playback error",
"VOD_AUTO_FAILOVER_DESCRIPTION": "When a movie fails to play and the same film exists in another playlist, switch to it automatically and keep the timecode. Off by default; the switch is always announced because another source can carry a different dub.",
"NAV_PARENTAL": "Parental lock",
"PARENTAL_LOCK": {
"TITLE": "Parental lock",
"DESCRIPTION": "Hide chosen categories behind a PIN. Locked categories, their channels and titles are removed from the whole app until the PIN is entered.",
"ENABLE": "Enable parental lock",
"ENABLE_DESCRIPTION": "Turning it on asks for a new PIN. Turning it off asks for the current PIN; your locks are kept for later.",
"STATUS": "Current state",
"STATUS_LOCKED": "Locked — locked categories are hidden.",
"STATUS_UNLOCKED": "Unlocked — locked categories are visible until the app locks again.",
"LOCK_NOW": "Lock now",
"UNLOCK": "Unlock",
"RELOCK": "Lock again after",
"RELOCK_DESCRIPTION": "Minutes without interaction before the app locks itself again. Playback counts as interaction. Restarting the app always locks.",
"RELOCK_NEVER": "Only when restarting the app",
"RELOCK_MINUTES": "{{minutes}} minutes of inactivity",
"CHANGE_PIN": "Change PIN",
"CHANGE_PIN_DESCRIPTION": "Asks for the current PIN first.",
"HOW_TO_LOCK": "Choosing what to lock",
"HOW_TO_LOCK_DESCRIPTION": "Open a source, then use “Manage categories” (the tune icon above the category list; “Manage groups” in an M3U playlist): every row has a lock toggle, and Stalker offers “Lock adult (18+)” for genres the portal flags. Right-click a category or group for a quick Lock / Unlock.",
"DISCLAIMER": "This is a child lock, not a security feature: the app's data files are readable by anyone with access to this computer.",
"ENABLED_TOAST": "Parental lock enabled",
"DISABLED_TOAST": "Parental lock disabled",
"PIN_CHANGED_TOAST": "PIN changed",
"LOCKED_TOAST": "Locked"
}
},
"THEMES": {
"DARK_THEME": "Dark",
"LIGHT_THEME": "Light",
"SYSTEM_THEME": "System"
},
"AUDIO_PLAYER": {
"PLAY": "Play",
"PAUSE": "Pause",
"PREVIOUS_STATION": "Previous station",
"NEXT_STATION": "Next station",
"MUTE": "Mute",
"UNMUTE": "Unmute",
"VOLUME": "Volume"
},
"EMBEDDED_MPV": {
"PLAYER": {
"BACK": "Back",
"RETRY": "Retry",
"STALLED": "This stream is taking longer than expected to start.",
"PLAYBACK_FAILED": "Embedded MPV playback failed.",
"RECONNECTING": "Connection lost. Reconnecting… attempt {{attempt}} of {{maxAttempts}}",
"STREAM_ENDED": "The live stream ended.",
"CHECKING_SUPPORT": "Checking embedded MPV support...",
"NOT_AVAILABLE": "Embedded MPV is not available in this environment.",
"LOADING_STREAM": "Loading stream…",
"PLAY": "Play",
"PAUSE": "Pause",
"PREVIOUS_EPISODE": "Previous episode",
"NEXT_EPISODE": "Next episode",
"BACK_10_SECONDS": "Back 10 seconds",
"FORWARD_10_SECONDS": "Forward 10 seconds",
"LIVE_STREAM": "Live stream",
"PLAYBACK_POSITION": "Playback position",
"MUTE": "Mute",
"UNMUTE": "Unmute",
"MUTED": "Muted",
"VOLUME": "Volume",
"VOLUME_LABEL": "Volume {{percent}}%",
"AUDIO_TRACKS": "Audio tracks",
"SUBTITLES": "Subtitles",
"SUBTITLES_OFF": "Off",
"QUALITY": "Quality",
"QUALITY_AUTO": "Auto",
"TRACK_DEFAULT": "Default",
"AUDIO_TRACK_FALLBACK": "Audio {{index}}",
"SUBTITLE_TRACK_FALLBACK": "Subtitle {{index}}",
"PLAYBACK_SPEED": "Playback speed",
"SPEED_TOOLTIP": "Speed: {{speed}}",
"ASPECT_RATIO": "Aspect ratio",
"ASPECT_TOOLTIP": "Aspect: {{aspect}}",
"ASPECT_DEFAULT": "Default",
"START_RECORDING": "Start recording",
"STOP_RECORDING": "Stop recording",
"RECORDING": "Recording",
"RECORDING_SAVED": "Recording saved",
"RECORDING_FAILED": "Recording failed",
"RECORDING_FAILED_TO_START": "Recording failed to start.",
"RECORDING_FAILED_TO_STOP": "Recording failed to stop.",
"SAVED_TO": "Saved to {{path}}",
"ENTER_PICTURE_IN_PICTURE": "Enter picture-in-picture",
"EXIT_PICTURE_IN_PICTURE": "Exit picture-in-picture",
"ENTER_FULLSCREEN": "Enter fullscreen",
"EXIT_FULLSCREEN": "Exit fullscreen",
"CHANNEL_LIST": "Channel list",
"HIDE_CHANNEL_LIST": "Hide channel list",
"EPISODE_LIST": "Episode list",
"HIDE_EPISODE_LIST": "Hide episode list",
"SEARCH_CHANNELS": "Search channels",
"SEARCH_IN": "Search in {{title}}",
"CLEAR_SEARCH": "Clear search",
"LOAD_SUBTITLE_FILE": "Load subtitle file…",
"SUBTITLE_DELAY": "Subtitle delay",
"SUBTITLE_DELAY_DECREASE": "Show subtitles earlier",
"SUBTITLE_DELAY_INCREASE": "Show subtitles later",
"SUBTITLE_DELAY_RESET": "Reset subtitle delay",
"SUBTITLE_SIZE": "Subtitle size",
"SUBTITLE_COLOR": "Subtitle color",
"SUBTITLE_COLOR_DEFAULT": "Default",
"SUBTITLE_COLOR_WHITE": "White",
"SUBTITLE_COLOR_YELLOW": "Yellow",
"SUBTITLE_COLOR_CYAN": "Cyan",
"STREAM_INFO": "Stream info",
"STATS_RESOLUTION": "Resolution",
"STATS_FRAME_RATE": "Frame rate",
"STATS_NOMINAL_FRAME_RATE": "Source frame rate",
"STATS_STREAM_BITRATE": "Stream bitrate",
"STATS_VIDEO": "Video",
"STATS_AUDIO": "Audio",
"STATS_AUDIO_CHANNELS": "Channels",
"STATS_SAMPLE_RATE": "Sample rate",
"STATS_CONTAINER": "Container",
"STATS_BUFFER": "Buffer",
"STATS_DROPPED_FRAMES": "Dropped frames",
"STATS_UNAVAILABLE": "No stream data yet"
}
},
"PLAYBACK_DIAGNOSTICS": {
"STAGE_LOADER": "Stream loading",
"STAGE_DEMUX": "Container parsing",
"DETAIL_STAGE": "Failure stage",
"DETAIL_DRM_SYSTEMS": "DRM declared by source",
"STAGE_MANIFEST": "Manifest loading",
"STAGE_PLAYLIST": "Media playlist loading",
"STAGE_SEGMENT": "Media segment loading",
"STAGE_KEY": "Encryption key loading",
"STAGE_LICENSE": "DRM license exchange",
"STAGE_MEDIA": "Media processing",
"UNSUPPORTED_CONTAINER": {
"TITLE": "This stream container is likely unsupported by the browser player",
"DESCRIPTION": "The browser player may not decode this container inline. Copy the stream URL and open it in an external player such as MPV, VLC, or IINA for broader codec support."
},
"UNSUPPORTED_CODEC": {
"TITLE": "This stream codec is likely unsupported by the browser player",
"DESCRIPTION": "The stream advertises codecs that the browser player may not decode. Copy the stream URL and open it in an external player such as MPV, VLC, or IINA."
},
"MEDIA_DECODE_ERROR": {
"TITLE": "The browser player could not decode this stream",
"DESCRIPTION": "Playback started but the media pipeline failed while decoding. An external player may handle this stream better."
},
"NETWORK_ERROR": {
"TITLE": "The stream could not be loaded",
"DESCRIPTION": "The player reported a network or provider loading error. Check the stream URL, headers, or provider availability."
},
"BROWSER_ACCESS_ERROR": {
"TITLE": "The browser player could not access this stream",
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
},
"UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.",
"DRM_OR_ENCRYPTION": {
"TITLE": "This stream may be encrypted or DRM-protected",
"DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required."
},
"UNKNOWN_PLAYBACK_ERROR": {
"TITLE": "The browser player reported a playback error",
"DESCRIPTION": "The stream failed in the built-in player, but the error did not identify a specific codec, container, or network cause."
},
"NATIVE_FALLBACK_TITLE": "Open it in a native player instead",
"INLINE_FAILURE_TITLE": "Copy the URL or try again",
"UNTRANSFERABLE_FAILURE_TITLE": "Protected playback could not continue",
"RECOMMENDATIONS_LABEL": "Recommended recovery actions",
"ACTION_TRY_PLAYER": "Try {{player}}",
"ACTION_TRY_PLAYER_HINT": "Temporary for this item; your saved player stays unchanged",
"REASON_RETRY_TRANSIENT_FAILURE": "Retry the same player after a temporary loading failure",
"REASON_RETRY_UNKNOWN_FAILURE": "Retry because the failure did not identify another compatible player",
"REASON_ALTERNATIVE_SOURCE_AVAILABLE": "Try another available source for the same content",
"REASON_DIFFERENT_ENGINE_FAMILY": "This player uses a different browser playback engine",
"REASON_EXTERNAL_CODEC_OR_CONTAINER_SUPPORT": "Native players support more codecs and containers",
"REASON_EXTERNAL_BROWSER_ACCESS": "A native player may avoid browser access restrictions",
"REASON_COMPATIBLE_DRM_PATH": "This target is compatible with the available encryption data",
"ACTION_OPEN_MPV": "Open in MPV",
"ACTION_OPEN_VLC": "Open in VLC",
"ACTION_OPENING_MPV": "Opening MPV…",
"ACTION_OPENING_VLC": "Opening VLC…",
"ACTION_REOPEN_MPV": "Open MPV again",
"ACTION_REOPEN_VLC": "Open VLC again",
"ACTION_RETRY_MPV": "Try MPV again",
"ACTION_RETRY_VLC": "Try VLC again",
"EXTERNAL_OPENING": "Opening player…",
"EXTERNAL_STARTED": "Player started",
"EXTERNAL_PLAYING": "Playing",
"EXTERNAL_FAILED": "External player error",
"ACTION_OPEN_MPV_HINT": "configured player",
"ACTION_OPEN_VLC_HINT": "configured player",
"ACTION_COPY_URL": "Copy stream URL",
"ACTION_RETRY": "Retry",
"DETAILS_SUMMARY": "Technical details",
"CODEC_HINT": "Detected {{codecs}}. Chromium/Electron browser players often have limited support for these codecs.",
"DETAIL_CODE": "Diagnostic code",
"DETAIL_PLAYER": "Player",
"DETAIL_SOURCE": "Source",
"DETAIL_CONTAINER": "Container",
"DETAIL_MIME_TYPE": "MIME type",
"DETAIL_VIDEO_CODECS": "Video codecs",
"DETAIL_AUDIO_CODECS": "Audio codecs",
"DETAIL_NATIVE_ERROR_CODE": "Native error code",
"DETAIL_NATIVE_ERROR_MESSAGE": "Native error message",
"DETAIL_ERROR_DETAILS": "Error details",
"DRM_CONFIGURATION_UNSUPPORTED": "This player does not support the stream’s DRM configuration. Ask your provider for a compatible stream.",
"DRM_CONFIGURATION_UNAVAILABLE": "The requested DRM configuration is unavailable in this environment. Check the browser’s protected-content settings or ask your provider for a compatible stream.",
"LICENSE_REQUEST_FAILED": "The player could not obtain a DRM license. Check your connection and playback access with your provider.",
"LICENSE_RESPONSE_REJECTED": "The DRM module rejected the license response. Contact your provider to check the license.",
"LICENSE_SERVER_MISSING": "No license server is configured for this protected stream. Ask your provider for the required playback configuration.",
"SEGMENT_ACCESS_DENIED": "The server denied access to the media segments. Check playback access with your provider.",
"ACTION_COPY_DIAGNOSTIC": "Copy diagnostics",
"REPORT_COPIED": "Diagnostics copied",
"COPY_FAILED": "Copy failed. Try again.",
"REPORT_PRIVACY": "Copies technical facts without stream URLs, credentials or raw error messages."
},
"LAYOUT": {
"HIDE_CHANNELS_LIST": "Hide channels list",
"SHOW_CHANNELS_LIST": "Show channels list",
"TOGGLE_SIDEBAR_TOOLTIP": "Toggle channels list (⌘/Ctrl+B)",
"CHANNELS_LIST_HIDDEN": "The channels list is hidden",
"CHANNELS_LIST_HIDDEN_HINT": "Bring it back with the button below or press ⌘/Ctrl+B.",
"HIDE_CATEGORIES": "Hide categories",
"SHOW_CATEGORIES": "Show categories",
"SHOW_CATEGORIES_PANEL": "Show categories panel",
"CHOOSE_CATEGORY": "Choose category",
"HIDE_PANELS": "Hide categories and channels",
"HIDE_PANELS_TOOLTIP": "Hide panels (⌘/Ctrl+B)",
"SHOW_PANELS": "Show categories and channels",
"SHOW_PANELS_TOOLTIP": "Show panels (⌘/Ctrl+B)"
},
"CHANNELS": {
"SHOW_PLAYING_CHANNEL": "Show playing channel",
"UPLOAD_OR_SELECT_OTHER_PLAYLIST": "Upload or select other playlist",
"ALL_CHANNELS": "All channels",
"GROUPS": "Groups",
"MANAGE_GROUPS": "Manage groups",
"MANAGE_GROUPS_HINT": "Use manage groups to show groups again.",
"NO_VISIBLE_GROUPS": "No visible groups",
"SEARCH_GROUPS": "Search groups",
"UNGROUPED": "Ungrouped",
"UNNAMED_CHANNEL": "Unnamed Channel",
"FAVORITES": "Favorites",
"NO_FAVORITES": "No favorites yet",
"USE_STAR_TO_FAVORITE": "Please use 'star' icon to add channels to your favorites.",
"REMOVE_FAVORITE": "Remove from favorites",
"ADD_FAVORITE": "Add to favorites",
"SHOW_DETAILS": "Show channel details",
"MAP_EPG": "Map EPG channel",
"FAVORITES_UPDATED": "Favorites were updated!",
"SELECT_CHANNEL_PLAYBACK": "Please select a channel to start playback",
"SORT_BY": "Sort by",
"SORT_BY_DATE": "Sort by Date Added (Newest First)",
"SORT_BY_RATING": "Sort by Rating",
"SORT_BY_NAME": "Sort by Name (A-Z)",
"LOAD_MORE": "Load more",
"REMAINING": "remaining",
"LOADING": "Loading channels...",
"LOADING_MORE": "Loading more...",
"NO_SEARCH_RESULTS": "No channels found",
"NO_CHANNELS_FOUND": "No channels found",
"NO_GROUPS_FOUND": "No groups found",
"CATCHUP_AVAILABLE": "Catchup available",
"CATCHUP_AVAILABLE_DAYS": "Catchup available — {{days}} days",
"TRY_DIFFERENT_SEARCH": "Try a different search term",
"DETAILS_DIALOG": {
"TITLE": "Channel details",
"DESCRIPTION": "Read-only metadata parsed from the playlist file.",
"SUMMARY": "Summary",
"TVG": "TVG metadata",
"CATCHUP": "Catchup",
"HTTP": "HTTP headers",
"NAME": "Name",
"CHANNEL_ID": "Channel ID",
"STREAM_URL": "Stream URL",
"GROUP": "Group",
"RADIO": "Radio",
"CATCHUP_AVAILABLE": "Catchup available",
"WINDOW": "Archive window",
"PLAYBACK_SUPPORTED": "Playback supported",
"EPG_PARAMS": "EPG params",
"TIMESHIFT": "Timeshift",
"TVG_ID": "TVG ID",
"TVG_NAME": "TVG name",
"TVG_URL": "TVG URL",
"TVG_LOGO": "TVG logo",
"TVG_REC": "TVG rec",
"CATCHUP_TYPE": "Catchup type",
"CATCHUP_SOURCE": "Catchup source",
"CATCHUP_DAYS": "Catchup days",
"HTTP_ORIGIN": "Origin",
"HTTP_REFERRER": "Referrer",
"HTTP_USER_AGENT": "User-Agent",
"EMPTY": "Not provided",
"NOT_AVAILABLE": "Not available",
"DAYS_ONE": "1 day",
"DAYS_OTHER": "{{count}} days"
},
"GROUP_MANAGEMENT": {
"TITLE": "Manage groups",
"SELECTED": "Selected",
"SELECT_ALL": "Select all",
"DESELECT_ALL": "Deselect all",
"SEARCH_PLACEHOLDER": "Search groups...",
"NO_RESULTS": "No matching groups found",
"SAVE": "Save"
}
},
"TOP_MENU": {
"OPEN_EPG_GUIDE": "Programme guide"
},
"EPG": {
"NEXT_DAY": "Next day",
"PREVIOUS_DAY": "Previous day",
"ZOOM_IN": "Zoom in",
"ZOOM_OUT": "Zoom out",
"FILTER_CHANNELS": "Filter channels",
"CLOSE_FILTER": "Close filter",
"SEARCH_PROGRAMS": "Search programs",
"CLOSE_PROGRAM_SEARCH": "Close program search",
"LIVE_STREAM": "Live stream",
"ARCHIVE_PLAYBACK_UNAVAILABLE_TITLE": "Archive playback is unavailable",
"ARCHIVE_PLAYBACK_UNAVAILABLE_DESCRIPTION": "This provider exposes schedule history for the channel, but does not expose playable archive/catch-up playback.",
"EPG_NOT_AVAILABLE_CHANNEL_DESCRIPTION": "Please add/change the URL of the EPG list in the settings of the app.",
"FETCH_EPG": "Fetching EPG data...",
"ERROR": "Ooops, EPG could not be loaded.",
"DOWNLOAD_SUCCESS": "EPG was successfully downloaded.",
"NO_PROGRAM_INFO": "No program information available",
"PROGRAM_DIALOG": {
"PROGRAM_DETAILS": "Details about the TV program",
"TITLE": "Title",
"CATEGORY": "Category",
"PARENTAL_RATING_SYSTEM": "Rating",
"DESCRIPTION": "Description",
"LANGUAGE": "Language",
"SHOW_PROGRAM_DETAILS": "Show details about this program",
"EPISODE": "Episode",
"DURATION": "Duration",
"COPY_ARCHIVE_URL": "Copy archive URL",
"ARCHIVE_URL_COPIED": "Archive URL copied",
"ARCHIVE_URL_FAILED": "Could not copy the archive URL",
"ARCHIVE_URL_NOTICE": "The URL may contain account credentials. External players may also need your source’s HTTP headers.",
"DOWNLOAD_ARCHIVE": "Download programme (TS)",
"ARCHIVE_DOWNLOAD_QUEUED": "Programme added to Downloads",
"ARCHIVE_DOWNLOAD_FAILED": "Could not download this programme. It may no longer be available.",
"ARCHIVE_DOWNLOAD_TS_ONLY": "Archive downloads currently support TS streams only.",
"ARCHIVE_DOWNLOAD_EXISTS": "This programme is already in Downloads."
},
"FETCH_SUCCESS": "EPG was fetched successfully",
"IMPORT_PROGRESS": "EPG Import",
"CHANNELS": "channels",
"PROGRAMS": "programs",
"LOADING": "Loading",
"QUEUED": "Queued",
"IMPORT_PANEL_MINIMIZE": "Minimize EPG import panel",
"IMPORT_PANEL_EXPAND": "Expand EPG import panel",
"IMPORT_SUMMARY_LOADING": "{{count}} loading",
"IMPORT_SUMMARY_QUEUED": "{{count}} queued",
"TOTAL_CHANNELS": "Total channels",
"TOTAL_PROGRAMS": "Total programs",
"UP_TO_DATE": "EPG is up-to-date, no sync needed",
"RETRY": "Retry",
"ALLOW_PRIVATE_SOURCE": "Allow source",
"ALLOW_PRIVATE_SOURCE_TITLE": "Allow private-network EPG source?",
"ALLOW_PRIVATE_SOURCE_WARNING": "Only allow this if you trust the EPG source. IPTVnator will let this exact EPG URL connect to private or local network addresses.",
"TRUST_TLS_HOST": "Trust host",
"TRUST_TLS_HOST_TITLE": "Trust invalid certificate?",
"TRUST_TLS_HOST_WARNING": "Only continue if you trust this host. IPTVnator will allow invalid TLS certificates for this host, but other hosts still require valid certificates.",
"CURRENT_PROGRAM": "Current program",
"ARCHIVE_PLAYBACK": "Archive playback",
"COLLAPSE_PANEL": "Collapse EPG panel",
"EXPAND_PANEL": "Expand EPG panel",
"GUIDE": {
"TITLE": "Programme guide",
"CLOSE": "Close guide",
"CHANNEL": "Channel",
"TODAY": "Today",
"NOW": "Now",
"JUMP_NOW": "Jump to now",
"SCOPE": "Channels shown",
"ONLY_WITH_EPG": "Only with EPG",
"ONLY_WITH_EPG_HINT": "Hide channels without programme data",
"DENSITY_COMFORTABLE": "Comfortable rows",
"DENSITY_COMPACT": "Compact rows",
"ZOOM": "Zoom",
"FILTER_CHANNELS": "Filter channels…",
"SEARCH_PROGRAMMES": "Search programmes…",
"NO_RESULTS": "No programmes found",
"NO_PROGRAMME_INFO": "No programme information",
"NO_PROGRAMME_INFO_LONG": "No programme information for this channel",
"PLAYING": "Playing",
"NO_CHANNELS": "No channels match \"{{query}}\"",
"CLEAR_FILTER": "Clear filter",
"COLLAPSE_PLAYER": "Collapse player",
"EXPAND_PLAYER": "Expand player",
"KEYS": {
"CHANNEL": "channel",
"PROGRAMME": "programme",
"PLAY": "play",
"DETAILS": "details",
"NOW": "now",
"DAY": "day",
"CLOSE": "close"
}
},
"TIMELINE": {
"OPEN_GUIDE": "Open the programme guide",
"TODAY": "Today",
"NOW": "Now",
"JUMP_NOW": "Jump to now",
"RETURN_TO_LIVE": "Return to live",
"ON_NOW": "On now",
"MINUTES_LEFT": "min left",
"FROM_ARCHIVE": "From archive",
"WATCH": "Watch",
"WATCH_LIVE": "Watch live",
"WATCH_FROM_START": "Watch from start",
"ARCHIVE_UNAVAILABLE_NOTE": "Playback unavailable — this provider does not expose an archive.",
"CATCHUP_FAILED": "Couldn't start archive playback for this program",
"SCHEDULE_ONLY_NOTICE": "Schedule only. This provider exposes programme history but not catch-up — past programmes can't be played.",
"EMPTY_DAY_TITLE": "No programme for this day",
"EMPTY_DAY_DESCRIPTION": "The schedule for the selected day hasn't arrived yet. Other days have data.",
"JUMP_TODAY": "Go to today",
"JUMP_NEAREST": "Nearest day with programme",
"CHANNEL_UNMAPPED_TITLE": "No programme for this channel",
"CHANNEL_UNMAPPED_DESCRIPTION": "This channel isn't matched to the EPG source (no tvg-id found). Other channels are unaffected.",
"PROVIDER_NO_EPG_TITLE": "Provider doesn't supply a guide",
"PROVIDER_NO_EPG_DESCRIPTION": "This source doesn't expose a TV guide for any channel. If you need a schedule, ask your provider.",
"M3U_SETUP_TITLE": "Connect a programme guide",
"M3U_SETUP_DESCRIPTION": "M3U playlists need an external EPG source (XMLTV). Add a url-tvg link and the schedule will appear here.",
"OPEN_EPG_SETTINGS": "Open EPG settings",
"ERROR_TITLE": "Couldn't load the guide",
"ERROR_DESCRIPTION": "The EPG source didn't respond. Check your connection or refresh the source.",
"RETRY": "Retry",
"MINUTES_SHORT": "min",
"ZOOM": "Zoom",
"ZOOM_DAY": "Day overview",
"ZOOM_HOURS": "By hour",
"ZOOM_DETAIL": "Detailed",
"ZOOM_TOOLTIP": "Zoom: {{level}} · ⌘/Ctrl + scroll to fine-tune",
"GROUP_SHORT": "short progs",
"GROUP_EXPAND": "show ›"
}
},
"EPG_MAPPING_DIALOG": {
"TITLE": "Map EPG Channel",
"SUBTITLE": "Manually select an EPG channel for \"{{channelName}}\"",
"SEARCH_PLACEHOLDER": "Search EPG channels...",
"CURRENT_MAPPING": "Current mapping",
"NO_MAPPING": "No EPG mapping set",
"SAVE": "Save mapping",
"REMOVE": "Remove mapping",
"CLOSE": "Close",
"NO_RESULTS": "No EPG channels found",
"SEARCH_HINT": "Type at least {{min}} characters to search",
"SAVED": "EPG mapping saved",
"REMOVED": "EPG mapping removed",
"SAVE_FAILED": "Could not update the EPG mapping"
},
"LANGUAGES": {
"ARABIC": "العربية",
"MOROCCAN_ARABIC": "العربية (اللهجة المغربية)",
"ENGLISH": "English",
"KOREAN": "한국어",
"RUSSIAN": "Русский",
"GERMAN": "Deutsch",
"SPANISH": "Español",
"CHINESE": "简体中文",
"TRADITIONAL_CHINESE": "繁體中文",
"FRENCH": "Français",
"ITALIAN": "Italiano",
"TURKISH": "Türkçe",
"JAPANESE": "日本語",
"DUTCH": "Nederlands",
"BELARUSIAN": "Беларуская",
"POLISH": "Polski",
"PORTUGUESE": "Português",
"GREEK": "Ελληνικά",
"HUNGARIAN": "Magyar"
},
"YES": "Yes",
"NO": "No",
"MENU": {
"OPEN": "Open menu",
"SUPPORT_ARIA": "Support IPTVnator on GitHub",
"SETTINGS_ARIA": "Open settings",
"BUG_REPORT": "Report a bug",
"WHAT_IS_NEW": "What is new",
"ABOUT": "About",
"ABOUT_ARIA": "About the application",
"SUPPORT_PROJECT": "Support project"
},
"ABOUT": {
"TITLE": "About IPTVnator",
"DESCRIPTION": "Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup and more.",
"VERSION": "Version",
"GITHUB_TOOLTIP": "ITPVnator repository on GitHub",
"BUY_ME_A_COFFEE_TOOLTIP": "Buy me a coffee",
"TWITTER_TOOLTIP": "Share on Twitter"
},
"UPDATE_AVAILABLE": "Update available",
"REFRESH": "Refresh",
"XTREAM": {
"PLAY": "Play",
"OPENING_PLAYER": "Opening player...",
"NAME": "Name",
"RELEASE_DATE": "Release date",
"GENRE": "Genre",
"COUNTRY": "Country",
"ACTORS": "Actors",
"DIRECTOR": "Director",
"SIMILAR": "Similar",
"CREW_JOB_DIRECTOR": "Director",
"CREW_JOB_CREATOR": "Creator",
"ACTOR_FILMOGRAPHY": "Filmography",
"ACTOR_FILTER_ALL": "All",
"ACTOR_SCOPE_THIS_PORTAL": "This portal",
"ACTOR_SCOPE_ALL_PORTALS": "All portals",
"ACTOR_NO_RESULTS": "Nothing found for this filter",
"ACTOR_IN_LIBRARY": "In your library",
"ACTOR_SEARCH_IN_PORTAL": "Search in portal",
"ACTOR_BORN": "Born",
"ACTOR_DIED": "Died",
"DISCOVER_TITLE": "Discover",
"DISCOVER_RESULTS": "Popular titles",
"DISCOVER_MOVIES": "Movies",
"DISCOVER_SERIES": "Series",
"DISCOVER_EMPTY": "Nothing found for this selection. Discover needs TMDB metadata enabled in the settings.",
"SERIES_STATUS_RETURNING": "Returning",
"SERIES_STATUS_PLANNED": "Planned",
"SERIES_STATUS_IN_PRODUCTION": "In production",
"SERIES_STATUS_ENDED": "Ended",
"SERIES_STATUS_CANCELED": "Canceled",
"SERIES_STATUS_PILOT": "Pilot",
"DURATION": "Duration",
"CAST": "Cast",
"EPISODE_RUN_TIME": "Episode run time",
"RATING": "Rating",
"IMDB_RATING": " Rating IMDB",
"KINOPOISK_RATING": "Rating Kinopoisk",
"DESCRIPTION": "Description",
"YEAR": "Year",
"AGE": "Age",
"YOUTUBE_TRAILER": "YouTube Trailer",
"EPISODE": "Episode",
"RESUME": "Resume",
"RESTART": "Start Over",
"CONTINUE_WATCHING": "Continue Watching",
"PLAY_FIRST_EPISODE": "Play first episode",
"PLAY_EPISODE": "Play episode {{episode}}",
"RESUME_EPISODE": "Resume episode",
"PLAY_NEXT_EPISODE": "Play next episode",
"SERIES_WATCHED": "Series watched",
"WATCHED": "Watched",
"IN_PROGRESS": "In Progress",
"MARK_WATCHED": "Mark as Watched",
"MARK_UNWATCHED": "Mark as Unwatched",
"MARK_SEASON_WATCHED": "Mark season as watched ({{count}})",
"MARK_SEASON_UNWATCHED": "Mark season as unwatched",
"SEASON_MARKED_WATCHED": "{{count}} episodes marked as watched",
"SEASON_MARKED_UNWATCHED": "Season marked as unwatched",
"SEASON_MARKED_WATCHED_PARTIAL": "{{count}} marked · {{failed}} failed",
"SEASON_MARKED_UNWATCHED_PARTIAL": "{{count}} unmarked · {{failed}} failed",
"SEASON_WATCH_UPDATE_FAILED": "Updating the season failed",
"MARK_SERIES_WATCHED": "Mark series as watched ({{count}})",
"MARK_SERIES_WATCHED_ALL": "Mark series as watched",
"MARK_SERIES_UNWATCHED": "Mark series as unwatched",
"SERIES_MARKED_UNWATCHED": "Series marked as unwatched",
"SERIES_WATCH_UPDATE_FAILED": "Updating the series failed",
"SERIES_WATCH_MENU": "Series watch actions",
"MOVIE_MARKED_WATCHED": "Marked as watched",
"MOVIE_MARKED_UNWATCHED": "Marked as unwatched",
"MOVIE_WATCH_UPDATE_FAILED": "Updating the watched state failed",
"EPISODES_WATCHED": "{{count}} of {{total}} episodes watched",
"DETAIL_FALLBACK": {
"STATUS": "Portal metadata unavailable",
"NOTE": "Extended metadata was not provided by this portal.",
"STREAM_ID": "Stream ID",
"CATEGORY": "Category",
"CONTAINER": "Format",
"SOURCE_TITLE": "Source title"
},
"ACCOUNT_INFO": {
"TITLE": "Account Information",
"USER_INFO": "User Information",
"STATUS": "Status",
"USERNAME": "Username",
"ACTIVE_CONNECTIONS": "Active Connections",
"CREATED": "Created",
"EXPIRES": "Expires",
"TRIAL_ACCOUNT": "Trial Account",
"YES": "Yes",
"NO": "No",
"ALLOWED_FORMATS": "Allowed Formats",
"SERVER_INFO": "Server Information",
"LIVE_TV": "Live TV",
"MOVIES": "Movies",
"TV_SERIES": "TV Series",
"URL": "URL",
"PROTOCOL": "Protocol",
"TIMEZONE": "Timezone",
"SERVER_TIME": "Server Time",
"PORTS": "Ports",
"HTTP_PORT": "HTTP",
"HTTPS_PORT": "HTTPS",
"RTMP_PORT": "RTMP"
},
"CATEGORY_MANAGEMENT": {
"TITLE": "Manage Categories",
"LOADING": "Loading categories...",
"SELECTED": "Total selected",
"SELECT_ALL": "Select All",
"DESELECT_ALL": "Deselect All",
"SELECT_FILTERED": "Select Filtered",
"DESELECT_FILTERED": "Deselect Filtered",
"SEARCH_PLACEHOLDER": "Search categories...",
"NO_RESULTS": "No matching categories found",
"NO_CATEGORIES": "No categories available",
"SAVE": "Save"
}
},
"PORTALS": {
"REQUESTS_PAUSED": {
"TITLE": "Requests temporarily paused",
"DESCRIPTION": "Requests were paused after repeated connection failures. Retry now to contact the portal immediately.",
"RETRY": "Retry now"
},
"ALL_CATEGORIES": "All categories",
"MY_FAVORITES": "My favorites",
"ADD_TO_FAVORITES": "Add to favorites",
"REMOVE_FROM_FAVORITES": "Remove from favorites",
"REMOVED_FROM_FAVORITES": "Removed from favorites",
"ADDED_TO_FAVORITES": "Added to favorites",
"FAVORITES": "Favorites",
"RECENTLY_VIEWED": "Recently viewed",
"THIS_PLAYLIST": "This playlist",
"ALL_PLAYLISTS": "All playlists",
"LIVE_TV": "Live TV",
"MOVIES": "Movies",
"SERIES": "Series",
"SEARCH": "Search",
"NO_FAVORITES": "No favorites yet",
"NO_RECENT_ITEMS": "No recently viewed items",
"REMOVE_FROM_RECENT": "Remove from recently viewed",
"BROWSE_ALL_MOVIES": "Browse all movies",
"BROWSE_ALL_SERIES": "Browse all series",
"BROWSE_ALL_LIVE": "Browse all live TV",
"VIEW_IN_PORTAL": "View in portal",
"VIEW_IN_PORTAL_TOOLTIP": "Open in {{name}}",
"SIDEBAR": {
"MAIN": "Main",
"MOVIES": "Movies",
"LIVE_TV": "Live TV",
"SERIES": "Series",
"LIBRARY": "Library",
"SEARCH": "Search",
"RECENT": "Recent",
"RECENTLY_ADDED": "Recently added",
"FAVORITES": "Favorites"
},
"ERROR_VIEW": {
"IMPORT_CANCELLED": {
"TITLE": "Import cancelled",
"DESCRIPTION": "The playlist import was cancelled. Retry when you want to continue loading this source."
},
"ACCOUNT_EXPIRED": {
"TITLE": "Account expired",
"DESCRIPTION": "This account has been expired. Please check the credentials in playlist settings or remove it."
},
"ACCOUNT_INACTIVE": {
"TITLE": "Account inactive",
"DESCRIPTION": "This account is inactive. Please check the credentials in playlist settings or remove it."
},
"UNAUTHORIZED": {
"TITLE": "Unauthorized",
"DESCRIPTION": "Please check the credentials in playlist settings or remove it."
},
"NOT_FOUND": {
"TITLE": "Portal not found",
"DESCRIPTION": "Please check the credentials and portal url in playlist settings or remove it."
},
"PORTAL_UNAVAILABLE": {
"TITLE": "Portal unavailable",
"DESCRIPTION": "The portal could not be reached. Check the server URL or retry when the source is available again."
},
"EMPTY_CATEGORY": {
"TITLE": "No content in this category",
"DESCRIPTION": "Select another category or switch the content type."
},
"UNKNOWN_ERROR": {
"TITLE": "Something went wrong",
"DESCRIPTION": "Unknown error, please try again later"
},
"NO_CATEGORY_SELECTED": {
"TITLE": "No category selected",
"DESCRIPTION": "Please select a category to see the content"
},
"STALKER_LOGIN_REQUIRED": "The portal requires a login and password. Import the portal again and fill in the username and password fields.",
"STALKER_DEVICE_CONFLICT": "The portal has a different device ID registered for this MAC address. Restore the device ID you used first, or ask your provider to reset the device for this MAC.",
"PLAYLIST_SETTINGS": "Playlist Settings",
"HOME": "Home",
"DELETE": "Delete"
},
"EMPTY_LIST_VIEW": {
"TITLE": "No results found",
"NO_SEARCH_RESULTS": "Nothing found, try to change your search request."
},
"SEARCH_VIEW": {
"INITIAL_TITLE": "Search for content",
"INITIAL_DESCRIPTION": "Enter at least 3 characters to search across live TV, movies and series.",
"RESULTS_FOUND": "Found {{count}} results",
"NO_RESULTS_FOR": "No results found for \"{{term}}\"",
"GROUP_BY_PLAYLIST": "Group results by playlist",
"VISIBLE_CATEGORIES_ONLY": "Visible categories only",
"GLOBAL_SEARCH_SOURCE_NOTE": "Global search includes results from Xtream and M3U playlists.",
"GLOBAL_INITIAL_DESCRIPTION": "Enter at least 2 characters to search across Xtream and M3U playlists.",
"LOADING_MORE_RESULTS": "Loading more results..."
},
"STREAM_URL_COPIED": "Stream URL copied to clipboard",
"COPY_STREAM_URL": "Copy Stream URL",
"NOW_PLAYING": "Now playing",
"UP_NEXT": "Up next",
"CLOSE_PLAYER": "Close player",
"ABOUT": "About",
"SEASONS_AND_EPISODES": "Seasons and Episodes",
"SEASON_TAB": "Season {{number}}",
"EPISODE_COUNT_ONE": "1 episode",
"EPISODE_COUNT_OTHER": "{{count}} episodes",
"BACK_TO_PLAYING_EPISODE": "Back to playing episode",
"GRID_VIEW": "Grid view",
"LIST_VIEW": "List view",
"NO_EPISODES_AVAILABLE": "No episodes available",
"NO_EPISODES_AVAILABLE_MESSAGE": "This series is listed by your provider, but no seasons or episodes are available to play.",
"SEASON_EMPTY": "This season is empty",
"SEASON_EMPTY_MESSAGE": "This season is listed by your provider, but no playable episodes are available.",
"EPISODE_INFO": "Episode details",
"SELECT_CATEGORY": "Select a category",
"PAGE": "Page",
"CONTENT_NOT_AVAILABLE": "This content is not available on this server",
"PLAYBACK_ERROR": "Failed to get playback URL",
"LOADING_SEASONS": "Loading seasons...",
"LOADING_EPISODES": "Loading episodes...",
"EPISODES_LOAD_FAILED": "The episodes could not be loaded.",
"LOADING_ALL_CHANNELS": "Loading full channel list…",
"REFRESH_CHANNEL_LIST": "Refresh channel list",
"NO_CHANNELS_IN_CATEGORY": "No channels in this category",
"ITEM": "item",
"ITEMS": "items",
"NO_EPISODES": "No episodes available",
"ALL_RADIO": "All radio",
"MULTI_SOURCE": {
"SOURCES": "Sources",
"SOURCE": "Source",
"SOURCES_FOR": "Sources for “{{title}}”",
"OPEN_SOURCES": "Show alternative sources",
"MATCHED_BY_TMDB": "matched by TMDB",
"MATCHED_BY_TITLE": "matched by title",
"MATCH_BY_TITLE": "by title",
"PLAYING": "Playing",
"CURRENT": "Current",
"PLAY_FROM_SOURCE": "Play from this source",
"PIN_SOURCE": "Make this the main source",
"UNPIN_SOURCE": "Unpin this source",
"CHECK": "check",
"CHECK_TOOLTIP": "Check availability",
"PROBE_OK": "available",
"PROBE_FAIL": "unavailable",
"PROBE_CHECKING": "checking",
"AUTO_FAILOVER": "Auto-switch on error",
"PLAYING_FROM": "Playing from:",
"SWITCH_TITLE": "Source unavailable — switching to {{playlist}}",
"SWITCH_DETAIL": "resuming at {{timecode}}",
"SWITCH_AUDIO_WARNING": "the dub may differ",
"SWITCHED_TO": "Switched to {{playlist}}",
"UNDO": "Undo",
"CHOOSE_OTHER": "Choose another",
"TRY_ANOTHER_SOURCE": "Try another source",
"ERROR_HAS_ALTERNATIVES": "{{playlist}} is not serving this stream. This movie is in your other playlists:",
"RESUME_KEPT": "timecode will be kept · {{timecode}}",
"ALL_SOURCES_TRIED": "Every source has been tried.",
"ALSO_FOUND_IN_ONE": "— also found in 1 other playlist",
"ALSO_FOUND_IN_OTHER": "— also found in {{count}} other playlists",
"CHECK_ALL": "check all",
"FILTER_PLACEHOLDER": "Filter by playlist",
"NO_MATCHES": "No playlists match that filter",
"COPIES": "{{count}} copies in this playlist",
"MORE_SOURCES": "+{{count}} more in the sources list",
"FILTER_ALL": "All",
"FILTER_AVAILABLE": "Available",
"FILTER_HD": "HD+",
"ALL_LANGUAGES": "All languages",
"SAME_AS_ABOVE": "same as above",
"SHOWING_OF_TOTAL": "{{visible}} of {{total}}"
},
"GRID": {
"LOADING_MORE": "Loading more…",
"LOAD_MORE_FAILED": "Couldn't load more items",
"RETRY": "Retry"
}
},
"INFORMATION": "Information",
"DOWNLOADS": {
"RECOVERY": {
"TITLE": "File recovery needed",
"MESSAGE": "A file unrelated to this download was preserved at: {{path}}. Recover any content you need, delete this recovery copy, then try again.",
"COPY_PATH": "Copy recovery path"
},
"TITLE": "Downloads",
"DOWNLOAD": "Download",
"PLAY_LOCAL": "Play Local",
"DOWNLOAD_SEASON": "Download season ({{count}})",
"DOWNLOAD_SEASON_ARIA": "Download season, {{count}} episodes available",
"ADDING_TO_QUEUE": "Adding to queue…",
"EPISODE_DOWNLOAD_ARIA": "Download {{title}}",
"EPISODE_DOWNLOAD_PENDING_ARIA": "{{title}} is already in the download queue",
"EPISODE_DOWNLOAD_FAILED": "The episode could not be added to downloads.",
"SEASON_QUEUE_RESULT": "Added {{added}} · Skipped {{skipped}}",
"SEASON_QUEUE_RESULT_WITH_FAILURES": "Added {{added}} · Skipped {{skipped}} · Failed {{failed}}",
"EMPTY": "No downloads yet",
"EMPTY_HINT": "Download movies and episodes to watch offline",
"NO_PLAYLISTS_TITLE": "Add a playlist to start downloading",
"NO_PLAYLISTS_BODY": "Once you add a playlist, you can save movies and episodes here for offline playback.",
"NO_ITEMS_BODY": "Use the download button on any movie or episode to save it for offline playback.",
"NO_FILTER_MATCH": "No downloads match the current filter",
"NO_FILTER_MATCH_HINT": "Try a different search term",
"NOT_AVAILABLE": "Downloads not available",
"DESKTOP_ONLY": "This feature is only available in the desktop app",
"NO_FOLDER": "No download folder selected",
"CHANGE_FOLDER": "Change Folder",
"CLEAR_COMPLETED": "Clear Completed",
"CLEAR_COMPLETED_DIALOG": {
"TITLE": "Clear completed downloads",
"MESSAGE": "This removes completed, failed, and canceled entries from the current downloads view. It does not delete any files that were already downloaded to disk."
},
"SOURCE_PLAYLIST_MISSING": "This download can no longer open in the library because its source playlist was removed.",
"FILE_NOT_FOUND": "This downloaded file is no longer available on disk.",
"FILE_ACTION_ERROR": "The file action could not be completed.",
"ACTION_FAILED": "Action failed",
"PAUSE": "Pause",
"RESUME": "Resume",
"CANCEL": "Cancel",
"DOWNLOADED_REVEAL": "Downloaded — show in folder",
"DOWNLOADING_PERCENT": "Downloading… {{percent}}%",
"CANCEL_CONFIRM_TITLE": "Cancel download",
"CANCEL_CONFIRM_MESSAGE": "Stop this download? The partially downloaded file will be discarded.",
"RETRY": "Retry",
"REMOVE": "Remove",
"PLAY": "Play",
"REVEAL": "Show in Folder",
"COPY_URL": "Copy download URL",
"URL_COPIED": "Download URL copied to clipboard",
"URL_COPY_FAILED": "Failed to copy URL to clipboard",
"STATUS": {
"QUEUED": "Queued",
"DOWNLOADING": "Downloading",
"COMPLETED": "Completed",
"FAILED": "Failed",
"CANCELED": "Canceled",
"PAUSED": "Paused",
"FILE_MISSING": "File missing",
"RECORDING": "Recording",
"INTERRUPTED": "Interrupted"
},
"ACTIVE_COUNT": "{{count}} active",
"TRACKED_DOWNLOADS": "Tracked downloads",
"CLEAR_FINISHED": "Clear finished",
"DOWNLOADING_NOW": "Downloading now",
"NEEDS_ATTENTION": "Needs attention",
"READY_TO_WATCH": "Ready to watch",
"OFFLINE": "Offline",
"OFFLINE_BADGE": "Offline",
"FILTER": {
"LABEL": "Filter downloads",
"ALL": "All",
"MOVIES": "Movies",
"SERIES": "Series",
"IN_PROGRESS": "In progress",
"RECORDINGS": "Recordings"
},
"RECORDING_NOW": "Recording now",
"RECORDINGS": "Recordings",
"RECORDING_BADGE": "Recording",
"STOP_RECORDING": "Stop recording",
"REMOVE_RECORDING_DIALOG": {
"TITLE": "Remove recording from manager?",
"MESSAGE": "This removes the entry from IPTVnator. The recorded file remains on disk."
},
"RECORDING_DETAIL": {
"PROGRAMS": "Recorded programs",
"RECORDED_FROM": "Recorded from {{playlist}}",
"MISSING_BODY": "The recording file is no longer on disk. A live broadcast cannot be re-recorded, but you can remove the entry from the manager.",
"FAILED_BODY": "This recording failed and produced no playable file."
},
"REMOVE_FROM_MANAGER": "Remove from manager",
"REMOVE_COMPLETED_DIALOG": {
"TITLE": "Remove from manager?",
"MESSAGE": "This removes the entry from IPTVnator. The downloaded media file remains on disk."
},
"REMOVE_PARTIAL_DIALOG": {
"TITLE": "Remove partial download?",
"MESSAGE": "This removes the entry and any retained partial download. It can no longer be resumed."
},
"CLEAR_FINISHED_DIALOG": {
"TITLE": "Clear finished downloads?",
"MESSAGE": "Completed media files remain on disk. Retained partial data for failed or canceled entries is deleted."
},
"ARTWORK_UNAVAILABLE": "Artwork unavailable",
"EPISODE_COUNT_ONE": "1 episode",
"EPISODE_COUNT_OTHER": "{{count}} episodes",
"MORE_ACTIONS": "More actions",
"MOVIE": "Movie",
"EPISODE": "Episode",
"SERIES": "Series",
"OPEN_ARTWORK": "Open {{title}}",
"OPEN_DETAILS": "Open details",
"OPEN_EPISODES": "Open downloaded episodes",
"SEASON": "Season {{season}}",
"SEASON_RANGE": "Seasons {{first}}–{{last}}",
"DOWNLOADED_EPISODES": "Downloaded episodes",
"OFFLINE_DETAIL": {
"AVAILABLE": "Available offline",
"PLAY": "Play offline",
"VIEW_IN_PORTAL": "View in portal",
"VIEW_IN_PORTAL_UNAVAILABLE": "The source item is no longer available",
"DOWNLOADED_EPISODES": "{{count}} downloaded episodes",
"FILE_SIZE": "{{size}}",
"NOT_FOUND_TITLE": "Download not found",
"NOT_FOUND_BODY": "This download is no longer available.",
"BACK": "Back to Downloads"
},
"ARIA": {
"OPEN": "Open {{title}}",
"POSTER_UNAVAILABLE": "Artwork unavailable for {{title}}",
"PROGRESS": "Download progress for {{title}}",
"PAUSE": "Pause {{title}}",
"CANCEL": "Cancel {{title}}",
"RESUME": "Resume {{title}}",
"REMOVE": "Remove {{title}} from manager",
"RETRY": "Retry {{title}}",
"MORE_ACTIONS": "More actions for {{title}}",
"COPY_URL": "Copy download URL for {{title}}",
"DOWNLOAD_AGAIN": "Download {{title}} again",
"RESTART_ARCHIVE": "Restart {{title}} from the beginning"
},
"DOWNLOAD_AGAIN": "Download again",
"CATCHUP": "TV programme",
"ARCHIVE_RESTART_NOTE": "Archive downloads restart from the beginning after an interruption."
},
"REMOTE_CONTROL": {
"TITLE": "Remote control",
"SUBTITLE": "Control your IPTV player remotely",
"UP_CHANNEL": "Channel Up",
"DOWN_CHANNEL": "Channel Down",
"HEADER": "IPTVNator Remote Control",
"FOOTER": "IPTVNator Remote Control"
},
"WORKSPACE": {
"FAVORITES_ONLY": "Favorites only",
"SORT_CUSTOM": "Custom order",
"SORT_DATE_DESC": "Date Added (Latest First)",
"SORT_DATE_ASC": "Date Added (Oldest First)",
"SORT_NAME_ASC": "Name A-Z",
"SORT_NAME_DESC": "Name Z-A",
"SORT_TOP_RATED": "Top rated",
"SORT_LOWEST_RATED": "Lowest rated first",
"REFINE_ACTION": "Refine",
"REFINE_SORT_SECTION": "Sort by",
"REFINE_RATING_SECTION": "Minimum rating",
"REFINE_CLEAR_RATING": "Clear {{value}}.0 and higher rating filter",
"FILTER_RATING": "Filter by rating",
"FILTER_RATING_ANY": "Any rating",
"FILTER_RATING_MIN": "{{value}}.0 and higher",
"SORT_LABEL": "Sort: ",
"SORT_SERVER": "Server sorting",
"CATEGORY_SORT_ARIA": "Sort categories",
"DASHBOARD": {
"ACTION_FAILED": "The action could not be completed. Please try again.",
"CONTINUE_WATCHING": "Continue Watching",
"LIVE_FAVORITES": "Live now on your favorites",
"LIVE_RECENT": "Continue with live TV",
"REMAINING_SECONDS": "{{seconds}}s left",
"REMAINING_MINUTES": "{{minutes}}m left",
"REMAINING_HOURS": "{{hours}}h left",
"REMAINING_HOURS_MINUTES": "{{hours}}h {{minutes}}m left",
"PERCENT_WATCHED": "{{value}}% watched",
"UNTITLED_SOURCE": "Untitled source",
"GLOBAL_FAVORITES": "Global Favorites",
"REMOVE_FROM_HISTORY": "Remove from history",
"RECENT_SOURCES": "Recently Used Sources",
"MANAGE_ALL": "Manage all",
"SEE_ALL": "See all",
"SEE_ALL_COUNT": "See all {{count}}",
"RECENTLY_WATCHED": "Recently Watched",
"XTREAM_RECENTLY_ADDED": "Recently Added on Xtream",
"TMDB_TRENDING": "Trending this week",
"TMDB_RECOMMENDED": "Recommended for you",
"TMDB_RECOMMENDED_BECAUSE": "Because you watched {{title}}",
"NO_HISTORY": "No items found for this filter.",
"NO_HISTORY_HINT": "Your watching history will appear here once you start playing content from your playlists.",
"XTREAM": "Xtream",
"STALKER": "Stalker",
"M3U": "M3U",
"STALKER_PORTAL": "Stalker Portal",
"PROVIDER": "Provider",
"TYPE_LIVE": "Live",
"TYPE_MOVIE": "Movie",
"TYPE_SERIES": "Series",
"SEASON_EPISODE_BADGE": "S{{season}}·E{{episode}}",
"NOT_YET_SYNCED": "Not yet synced",
"RECENTLY_WATCHED_LIVE_TV": "Recently watched live TV",
"FAVORITE_MOVIES_AND_SERIES": "Favorite movies & series",
"SOURCE_EXPIRES_IN_DAYS": "Expires in {{days}} d",
"SOURCE_EXPIRED": "Expired"
},
"SHELL": {
"BRAND_ALT": "IPTVnator",
"RAIL_DASHBOARD": "Dashboard",
"OPEN_DASHBOARD": "Open dashboard",
"RAIL_SOURCES": "Sources",
"OPEN_SOURCES": "Open sources",
"RAIL_GLOBAL_FAVORITES": "Favorites",
"RAIL_GLOBAL_RECENT": "Recently viewed",
"RAIL_GLOBAL_SEARCH": "Global search",
"RAIL_SETTINGS": "Settings",
"OPEN_SETTINGS": "Open settings",
"RAIL_LIBRARY": "Library",
"RAIL_MOVIES": "Movies",
"RAIL_LIVE": "Live TV",
"RAIL_SERIES": "Series",
"RAIL_RECENTLY_ADDED": "Recently added",
"RAIL_SEARCH": "Advanced search",
"RAIL_RECENT": "Recently viewed",
"RAIL_FAVORITES": "Favorites",
"RAIL_DOWNLOADS": "Downloads",
"EXTERNAL_PLAYBACK_CLOSE": "Close player",
"EXTERNAL_PLAYBACK_DISMISS": "Dismiss",
"EXTERNAL_PLAYBACK_OPENING": "Opening player…",
"EXTERNAL_PLAYBACK_STARTED": "Player started",
"EXTERNAL_PLAYBACK_PLAYING": "Playing",
"EXTERNAL_PLAYBACK_FAILED": "External player error",
"EXTERNAL_PLAYBACK_CLOSED": "Closed",
"RAIL_ALL_CHANNELS": "All channels",
"RAIL_GROUPS": "Groups",
"RAIL_CONTEXT_ACTIONS": "Section actions",
"SEARCH_LABEL": "Search",
"SEARCH_SOURCES_PLACEHOLDER": "Search sources (all playlists)...",
"SEARCH_SETTINGS_PLACEHOLDER": "Search settings...",
"SEARCH_GLOBAL_PLACEHOLDER": "Search all playlists...",
"SEARCH_PLAYLIST_PLACEHOLDER": "Search in this playlist...",
"SEARCH_SECTION_PLACEHOLDER": "Search in this section...",
"FILTER_SECTION_PLACEHOLDER": "Filter this section...",
"SEARCH_STATUS_LOADED_ONLY": "Loaded channels only",
"COMMAND_PALETTE_SHORTCUT": "Command palette (Ctrl/Cmd+K)",
"OPEN_COMMAND_PALETTE": "Open command palette",
"CONTEXT_DRAWER_CATEGORIES_TOGGLE": "Toggle the categories panel",
"CONTEXT_DRAWER_CATEGORIES_TOOLTIP": "Categories",
"CONTEXT_DRAWER_FILTERS_TOGGLE": "Toggle the filters panel",
"CONTEXT_DRAWER_FILTERS_TOOLTIP": "Filters",
"CONTEXT_DRAWER_SETTINGS_TOGGLE": "Toggle the settings sections panel",
"CONTEXT_DRAWER_SETTINGS_TOOLTIP": "Settings sections",
"ADD_PLAYLIST_ALL": "Add playlist",
"ADD_PLAYLIST": "Add playlist",
"OPEN_DOWNLOADS": "Open downloads",
"OPEN_CONTEXT_ACTIONS": "Open section actions",
"NO_SECTION_ACTIONS": "No actions for this section",
"PLAYLIST_INFO": "Playlist info",
"ACCOUNT_INFO": "Account info",
"REFRESH_PLAYLIST": "Refresh playlist",
"CLEAR_COMPLETED_DOWNLOADS_ALL": "Clear completed downloads (all playlists)",
"CLEAR_COMPLETED_DOWNLOADS_ALL_ARIA": "Clear completed downloads for all playlists",
"CLEAR_COMPLETED_DOWNLOADS_THIS_PLAYLIST": "Clear completed downloads (this playlist)",
"CLEAR_COMPLETED_DOWNLOADS_THIS_PLAYLIST_ARIA": "Clear completed downloads for this playlist",
"CLEAR_RECENTLY_VIEWED_SECTION": "Clear recently viewed",
"CLEAR_RECENTLY_VIEWED_SECTION_ARIA": "Clear recently viewed for this section",
"CLEAR_RECENTLY_VIEWED_TYPE": "Clear recently viewed {{type}}",
"CLEAR_RECENTLY_VIEWED_DIALOG_TITLE": "Clear recently viewed {{type}}?",
"CLEAR_RECENTLY_VIEWED_DIALOG_MESSAGE_PLAYLIST": "All {{type}} items from this playlist will be removed from your recently viewed history. This action cannot be undone.",
"CLEAR_RECENTLY_VIEWED_DIALOG_MESSAGE_ALL": "All {{type}} items across all playlists will be removed from your recently viewed history. This action cannot be undone.",
"CLEAR_FAVORITES_TYPE": "Clear {{type}} favorites",
"CLEAR_FAVORITES_DIALOG_TITLE": "Remove all {{type}} favorites?",
"CLEAR_FAVORITES_DIALOG_MESSAGE_PLAYLIST": "All {{type}} favorites from this playlist will be removed. This action cannot be undone.",
"CLEAR_FAVORITES_DIALOG_MESSAGE_ALL": "All {{type}} favorites across all playlists will be removed. This action cannot be undone.",
"XTREAM_CODE": "Xtream Code",
"STALKER_PORTAL": "Stalker Portal",
"CHANNELS_COUNT": "{{count}} channels",
"NO_SOURCES_AVAILABLE": "No sources available",
"ONE_SOURCE_AVAILABLE": "1 source available",
"SOURCES_AVAILABLE": "{{count}} sources available",
"GO_TO_DASHBOARD": "Back to dashboard",
"GO_TO_SOURCES": "Go to Sources",
"DROP_OVERLAY_TITLE": "Drop to add playlist",
"DROP_OVERLAY_BODY": "Release an .m3u or .m3u8 file anywhere in the workspace to import it.",
"DROP_OVERLAY_REJECTED_BODY": "Please drop an .m3u or .m3u8 file. Press Esc to dismiss.",
"DROP_OVERLAY_REJECTED_UNSUPPORTED": "Unsupported file type",
"DROP_OVERLAY_REJECTED_EMPTY": "That file is empty",
"DROP_OVERLAY_REJECTED_READ_ERROR": "Could not read that file",
"DROP_IMPORT_SUCCESS": "Importing \"{{title}}\"…",
"XTREAM_IMPORT_TITLE": "Syncing playlist",
"XTREAM_IMPORT_REMOTE_BADGE": "Remote source",
"XTREAM_IMPORT_LOCAL_BADGE": "Local library",
"XTREAM_IMPORT_DETAIL_REMOTE": "Waiting on the provider response.",
"XTREAM_IMPORT_DETAIL_LOCAL": "Preparing faster playlist switching for the next visit.",
"XTREAM_IMPORT_DETAIL_CACHED": "Reading the local library — no data is downloaded from the provider.",
"XTREAM_IMPORT_PREPARING": "Preparing local library...",
"XTREAM_IMPORT_LOADING_CACHED": "Loading the saved catalog from this device...",
"XTREAM_IMPORT_LOADING": "Fetching playlist data from source...",
"XTREAM_IMPORT_SAVING": "Saving playlist data locally...",
"XTREAM_IMPORT_RESTORING_FAVORITES": "Restoring favorites from local library...",
"XTREAM_IMPORT_RESTORING_RECENT": "Restoring recently viewed from local library...",
"XTREAM_IMPORT_PROGRESS": "{{type}} imported: {{current}} / {{total}}",
"XTREAM_IMPORT_CANCEL": "Stop sync",
"XTREAM_IMPORT_CANCELLING": "Stopping sync...",
"COMMANDS": {
"GLOBAL_SEARCH_LABEL": "Search all playlists",
"GLOBAL_SEARCH_DESCRIPTION": "Open global search",
"PLAYLIST_SEARCH_LABEL": "Advanced search this playlist",
"PLAYLIST_SEARCH_DESCRIPTION": "Open advanced playlist search",
"OPEN_GLOBAL_FAVORITES_LABEL": "Open global favorites",
"OPEN_GLOBAL_FAVORITES_DESCRIPTION": "Navigate to aggregated favorites",
"OPEN_DOWNLOADS_LABEL": "Open downloads",
"OPEN_DOWNLOADS_DESCRIPTION": "Navigate to downloads view",
"OPEN_GLOBAL_RECENT_LABEL": "Open recently viewed",
"OPEN_GLOBAL_RECENT_DESCRIPTION": "Open global recently viewed page",
"OPEN_SETTINGS_LABEL": "Open settings",
"OPEN_SETTINGS_DESCRIPTION": "Navigate to application settings",
"OPEN_SOURCES_LABEL": "Manage sources",
"OPEN_SOURCES_DESCRIPTION": "Navigate to source management",
"OPEN_DASHBOARD_LABEL": "Open dashboard",
"OPEN_DASHBOARD_DESCRIPTION": "Navigate to the dashboard",
"ADD_PLAYLIST_LABEL": "Add new source",
"ADD_PLAYLIST_DESCRIPTION": "Open add playlist dialog",
"ADD_PLAYLIST_M3U_LABEL": "Add M3U playlist",
"ADD_PLAYLIST_M3U_DESCRIPTION": "Open add dialog on the M3U file or URL tab",
"ADD_PLAYLIST_XTREAM_LABEL": "Add Xtream Codes playlist",
"ADD_PLAYLIST_XTREAM_DESCRIPTION": "Open add dialog on the Xtream Codes tab",
"ADD_PLAYLIST_STALKER_LABEL": "Add Stalker portal",
"ADD_PLAYLIST_STALKER_DESCRIPTION": "Open add dialog on the Stalker Portal tab",
"REFRESH_PLAYLIST_LABEL": "Refresh playlist",
"REFRESH_PLAYLIST_DESCRIPTION": "Re-sync data from remote source",
"PLAYLIST_INFO_LABEL": "Playlist details",
"PLAYLIST_INFO_DESCRIPTION": "Show current playlist information",
"ACCOUNT_INFO_LABEL": "Account info",
"ACCOUNT_INFO_DESCRIPTION": "Show Xtream server account details",
"OPEN_VIEW_DESCRIPTION": "Navigate to {{view}}",
"CLEAR_CURRENT_VIEW_DESCRIPTION": "Clear all visible {{type}} items in this view",
"OPEN_EPG_GUIDE_DESCRIPTION": "Open the programme guide for this playlist",
"GO_TO_VOD_LABEL": "Movies",
"GO_TO_VOD_DESCRIPTION": "Jump to movies section",
"GO_TO_LIVE_LABEL": "Live TV",
"GO_TO_LIVE_DESCRIPTION": "Jump to live TV section",
"GO_TO_SERIES_LABEL": "Series",
"GO_TO_SERIES_DESCRIPTION": "Jump to series section",
"SWITCH_PLAYER_LABEL": "Switch player to {{name}}",
"SWITCH_PLAYER_DESCRIPTION": "Set {{name}} as the active video player",
"SWITCH_PLAYER_FEEDBACK": "Player set to {{name}}",
"ACCOUNT_INFO_DESCRIPTION_STALKER": "Show Stalker portal account details",
"PARENTAL_LOCK_NOW_LABEL": "Lock now",
"PARENTAL_LOCK_NOW_DESCRIPTION": "Hide the parental-locked categories again",
"PARENTAL_UNLOCK_LABEL": "Enter parental PIN",
"PARENTAL_UNLOCK_DESCRIPTION": "Show the parental-locked categories"
},
"XTREAM_REFRESH_TITLE": "Refreshing playlist",
"XTREAM_REFRESH_COLLECTING_DATA": "Preserving your library data...",
"XTREAM_REFRESH_DELETING_CONTENT": "Removing cached streams...",
"XTREAM_REFRESH_DELETING_CATEGORIES": "Removing cached categories...",
"XTREAM_REFRESH_DETAIL_LOCAL": "Keeping favorites, watch history, hidden categories, and playback progress ready for restore after sync.",
"XTREAM_REFRESH_PROGRESS": "Local records processed: {{current}} / {{total}}",
"RAIL_RADIO": "Radio"
},
"SOURCES": {
"TITLE": "Sources",
"SUBTITLE": "Filter and sort playlists",
"TYPE": "Type",
"ALL": "All",
"M3U_PLAYLISTS": "M3U Playlists",
"XTREAM_PLAYLISTS": "Xtream Playlists",
"STALKER_PLAYLISTS": "Stalker Playlists",
"ALL_PLAYLISTS": "All Playlists",
"PLAYLIST_COUNT_ONE": "1 playlist",
"PLAYLIST_COUNT_OTHER": "{{count}} playlists"
},
"CONTEXT": {
"CATEGORIES": "Categories",
"MOVIE_CATEGORIES": "Movie Categories",
"SERIES_CATEGORIES": "Series Categories",
"LIVE_CATEGORIES": "Live Categories",
"XTREAM_SYNCING_MOVIES": "Syncing movie categories...",
"XTREAM_SYNCING_SERIES": "Syncing series categories...",
"XTREAM_SYNCING_LIVE": "Syncing live categories...",
"XTREAM_SOURCE": "Xtream source",
"STALKER_PORTAL": "Stalker portal",
"MANAGE_CATEGORIES": "Manage categories",
"LOAD_CATEGORIES_ERROR": "Unable to load categories",
"LOAD_CATEGORIES_ERROR_HINT": "Please retry or verify portal settings.",
"FILTER_BY_TYPE": "Filter by type",
"ITEM_COUNT_ONE": "1 item",
"ITEM_COUNT_OTHER": "{{count}} items",
"SEARCH": "Search",
"SEARCH_CATEGORIES": "Search categories",
"RADIO_CATEGORIES": "Radio Categories"
},
"COMMAND_PALETTE": {
"TITLE": "Command palette",
"SUBTITLE": "Global and contextual actions",
"SEARCH_PLACEHOLDER": "Search commands and settings",
"SEARCH_LABEL": "Filter commands",
"EMPTY": "No commands found",
"GROUP_GLOBAL": "Global actions",
"GROUP_PLAYLIST": "This playlist",
"GROUP_VIEW": "Current view",
"GROUP_SECTION": "This section",
"GROUP_RECENT": "Recently used",
"GROUP_SETTINGS": "Settings"
},
"SHORTCUTS": {
"TITLE": "Keyboard shortcuts",
"SUBTITLE": "Workspace, navigation, playback, and dialog shortcuts available in IPTVnator.",
"OPEN_TOOLTIP": "Keyboard shortcuts (?)",
"OPEN_ARIA": "Open keyboard shortcuts",
"PLATFORM": {
"MAC": "macOS layout",
"OTHER": "Windows/Linux layout"
},
"GROUPS": {
"GLOBAL": "Global",
"NAVIGATION": "Navigation",
"PLAYBACK": "Playback",
"DIALOGS": "Dialogs and lists"
},
"ITEMS": {
"OPEN_KEYBOARD_SHORTCUTS": "Open this shortcuts list",
"OPEN_COMMAND_PALETTE": "Open command palette",
"OPEN_GLOBAL_SEARCH": "Open global search",
"OPEN_RECENTLY_VIEWED": "Open recently viewed",
"SUBMIT_SHELL_SEARCH": "Submit workspace search",
"TOGGLE_WINDOW_FULLSCREEN": "Toggle app window fullscreen",
"ZOOM_IN_OUT": "Zoom the app in or out",
"RESET_ZOOM": "Reset app zoom",
"TOGGLE_SIDEBAR": "Toggle sidebar",
"M3U_CHANNEL_NUMBER": "Select M3U channel by number",
"PLAY_PAUSE": "Play or pause embedded MPV playback",
"TOGGLE_FULLSCREEN": "Toggle embedded MPV fullscreen",
"SEEK": "Seek embedded MPV playback by 5 seconds",
"ADJUST_VOLUME": "Adjust volume by 5%",
"MUTE_AUDIO": "Mute audio",
"CLOSE_PLAYER_POPOVERS": "Close embedded MPV popovers",
"COMMAND_PALETTE_NAVIGATION": "Move command palette selection",
"COMMAND_PALETTE_RUN": "Run selected command palette item",
"CLOSE_DIALOGS": "Close dialog or dismiss overlay",
"DOWNLOADS_OPEN_ITEM": "Open focused download item in the library"
}
},
"GLOBAL_FAVORITES": {
"TITLE": "Global Favorites",
"SUBTITLE": "Live TV from all playlists",
"SEARCH_PLACEHOLDER": "Search favorites...",
"NO_RESULTS": "No results",
"NO_RESULTS_HINT": "Try a different search term",
"EMPTY_TITLE": "No live TV favorites yet",
"EMPTY_HINT": "Star live channels from M3U, Xtream, or Stalker playlists to see them here.",
"EMPTY_PLAYER": "Select a channel to start watching",
"NO_PLAYLISTS_TITLE": "No favorites to show",
"NO_PLAYLISTS_BODY": "Add a playlist to start collecting favorites from live channels, movies, and series.",
"NO_ITEMS_TITLE": "No favorites yet",
"NO_ITEMS_BODY": "Tap the star icon on any channel, movie, or series to save it here.",
"UNKNOWN_CHANNEL": "Unknown"
},
"GLOBAL_RECENT": {
"NO_PLAYLISTS_TITLE": "Nothing watched yet",
"NO_PLAYLISTS_BODY": "Add a playlist and your watching history will appear here.",
"NO_ITEMS_TITLE": "Nothing watched yet",
"NO_ITEMS_BODY": "Start watching anything from your library and it will show up here."
}
},
"LOADING": "Loading",
"RETRY": "Retry",
"STALKER": {
"ACCOUNT_INFO": {
"TITLE": "Account Information",
"ACCOUNT": "Account",
"PORTAL_INFO": "Portal",
"LOGIN": "Login",
"STATUS": "Status",
"ACTIVE": "Active",
"INACTIVE": "Inactive",
"TARIFF_PLAN": "Tariff plan",
"EXPIRES": "Expires",
"DAYS_LEFT": "Days left",
"EXPIRED": "Expired",
"MAC_ADDRESS": "MAC address",
"PHONE": "Phone",
"PORTAL_URL": "Portal URL",
"PORTAL_TYPE_FULL": "Ministra portal",
"PORTAL_TYPE_LEGACY": "Legacy portal (portal.php)",
"CACHED_BADGE": "Saved data",
"REFRESH_FAILED": "The portal could not be reached — showing the data saved when the portal was added.",
"NO_ACCOUNT_DATA_TITLE": "No account details",
"NO_ACCOUNT_DATA_DESCRIPTION": "This portal does not publish account information for this device."
}
},
"STARTUP": {
"PREPARING": "Preparing your library",
"PREPARING_DETAIL": "Loading your sources and checking the programme guide. Large libraries may take a little longer.",
"FAILED": "Your sources could not be loaded",
"FAILED_DETAIL": "Retry to read your saved sources again. Your data has not been deleted."
},
"SOURCE_HEALTH": {
"RECHECK": "Check again",
"M3U_SCOPE": "Playlist URL, not individual channels",
"REASON": {
"available": "Available",
"disabled": "Account disabled",
"expired": "Subscription expired",
"auth": "Access denied; account status unconfirmed",
"http": "Server returned an error",
"timeout": "Check timed out",
"network": "Could not connect",
"paused": "Connection checks paused",
"invalid": "Unexpected response",
"unknown": "Not verified",
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
},
"PARENTAL_LOCK": {
"PIN_DIALOG": {
"UNLOCK_TITLE": "Enter parental PIN",
"UNLOCK_DESCRIPTION": "Locked categories stay hidden until the PIN is entered.",
"SET_TITLE": "Set parental PIN",
"SET_DESCRIPTION": "Choose a PIN that will be required to show locked categories.",
"PIN_LABEL": "PIN",
"CONFIRM_LABEL": "Repeat PIN",
"PIN_HINT": "{{min}} to {{max}} digits",
"WRONG_PIN": "Wrong PIN. Try again.",
"MISMATCH": "The two PINs do not match.",
"COOLDOWN": "Too many attempts. Wait 30 seconds and try again.",
"NO_RECOVERY": "There is no way to recover a forgotten PIN — only resetting the app data removes it.",
"SAVE": "Save PIN",
"UNLOCK": "Unlock",
"CONFIRM_TITLE": "Confirm parental PIN",
"CONFIRM_DESCRIPTION": "Enter the current PIN to change this setting."
},
"LOCKED_COUNT": "Locked",
"LOCK_CATEGORY": "Lock category",
"UNLOCK_CATEGORY": "Unlock category",
"LOCK_GROUP": "Lock group",
"UNLOCK_GROUP": "Unlock group",
"MANAGE_LOCKS": "Lock categories",
"MANAGE_LOCKS_DESCRIPTION": "Locked categories and their channels disappear from the whole app until the parental PIN is entered.",
"LOCK_CENSORED": "Lock adult (18+)",
"UNLOCK_ALL": "Unlock all",
"CENSORED_HINT": "The portal flags this category as adult content",
"SAVE_FAILED": "Saving the category locks failed",
"LOCKED_CATEGORIES_ROW": "{{count}} locked",
"UNLOCK_TO_SHOW": "Enter PIN to show",
"HEADER_LOCK": "Lock now (parental lock)",
"HEADER_UNLOCK": "Enter parental PIN"
}
}