Commit Graph
4 Commits
Author SHA1 Message Date
4grayandClaude Opus 5.5 2b400cb81d fix(i18n): translate the remaining hard-coded labels (#1871)
* fix(i18n): translate hard-coded labels, snackbars and missing keys

Catalog screens, snackbars and external player messages showed English
in every locale, and seven keys used in code were missing from en.json,
so ngx-translate rendered them raw.

- Catalog: "All items", item and channel counts, channel sort menus and
  tooltips, unnamed-category and empty-category labels, LIVE/PAUSED
  badges and the Xtream global search summary are translated. The Xtream
  and Stalker stores no longer bake an English name into the every-item
  sentinel; the facades return a null title and the view translates it.
- Snackbars: Xtream/Stalker request failures, the 413 upload error,
  backup export/import results and the category visibility failure use
  keys; every "Close" action uses CLOSE.
- External player: the main process sends an error code instead of an
  English sentence (player-error event, session errorCode, and a tag in
  rejected launch errors); the renderer, dock and VOD primary button
  translate it. The external player info dialog is translated.
- Adds the seven missing keys and 43 new ones, translated in all 18
  locales; seven legitimately identical values are baselined.
- tools/i18n/check-usage.mjs fails on keys used in code but missing from
  en.json; it runs in i18n:check (and so in CI through i18n:validate).

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

* fix(i18n): translate catalog counts in the template and skip inline template comments

- The category subtitle hands a key to the translate pipe instead of
  caching translate.instant(), so a cold start re-renders it once the
  language file loads.
- The Xtream live root count uses the singular/plural item keys, so one
  result no longer reads "1 channels".
- check-usage.mjs strips HTML comments inside inline templates of
  TypeScript files, so a commented-out key no longer fails the check.

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

* fix(i18n): check keys in parenthesised translate pipe operands

`(expanded() ? 'SHOW_LESS' : 'SHOW_MORE') | translate` yields keys that
neither precede the pipe directly nor contain a dot, so the usage check
missed them. It now reads the ternary and fallback branches of a
parenthesised operand; a literal compared in the condition is not read
as a key.

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

* test(e2e): expect the translated external player failure in the dock

A launch failure without an error code now shows the translated generic
status in the playback dock, with the raw main-process detail as its
tooltip. The ClearKey DASH flow asserted the raw English text.

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

* fix(playback): keep the IPC error tag out of the stored session detail

A tagged launch failure reached ExternalPlayerSession.error unchanged, so
the dock tooltip showed "[iptvnator:external-player:start-failed]". The
registry now strips the tag when it stores the detail; the rejected IPC
error keeps it for the renderer to read the code.

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

* test(web): expect translated portal request failure toasts

#1861's new resolved-failure specs asserted the English toast text; the
toasts now go through PORTALS.REQUEST_ERRORS keys, so the specs check
the key and its message/status params.

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

* fix(i18n): read only returned branches of a grouped translate operand

A literal at the start of a condition, as in
`('ERROR' === status() ? 'CLOSE' : 'CLOSE') | translate`, was taken for
a translation key, so a valid template could fail the usage check. A
grouped literal now counts only when it ends its operand (end of group,
`:`, `||` or `??`).

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

* fix(i18n): translate the remaining hard-coded labels

Follow-up to the UI-26 pass. The remaining English UI literals now come
from translation keys, translated in all 18 locales:

- Windows/Linux window controls, playlist switcher title and actions
  menu, the portal status tooltip, dashboard carousel roles and rail
  scroll buttons, the search placeholder, the card remove tooltip, the
  EPG offset unit, the REC chip, the Stalker EPG source label and the
  export file type.
- Embedded MPV failures raised in the renderer and the release-notes
  dialog without a bridge. Settings never showed its English reasons,
  so they are dropped.
- Unnamed Stalker episodes: data access leaves the title empty and the
  series view labels it after the TMDB overlay. Synthetic season names
  stay, because they key persisted episode progress.
- The phone remote-control page, which follows the first browser
  language with a translation and sets <html lang>.

Removes the dead getStatusMessage(), the unused favorites layout and the
translateWithFallback() helpers whose keys now exist.

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

* fix(remote-control): keep the remote build off shared-interfaces

The language resolver imported the Language enum, which made
remote-control-web depend on shared-interfaces. Its build-performance
chain then hit Nx's recursive-invocation guard through the existing
shared-interfaces/shared-logging build loop, failing the Electron E2E
and performance journey builds. The resolver now keeps its own list of
translation codes, and a spec checks it against the locale files the page
loads.

Also drops the deleted favorites layout from the zoneless checklist,
whose guard spec requires ticked entries to exist.

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

* perf(journeys): raise the launch DOM mutation baseline for translated attributes

Launch now sets 569 DOM mutations before the first dashboard card instead
of 557 (identical in all three CI iterations). The extra twelve come from
attributes this PR moved from static English to translated bindings on
the launch path: the window-control labels and tooltips on Linux, the
hero carousel and slide roles, and the rail scroll-button labels. A
translated attribute is a binding set after the element is attached, so
each costs a mutation. Accepted as a deliberate trade-off; it needs the
perf-baseline-increase label.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:22:31 +02:00
4grayandClaude Fable 5.1 7522c7689f fix(settings): honest update-channel check and fresh release notes (#1631)
* fix(settings): make the update-channel check honest and keep release notes fresh

Settings → About mixed two commit models: the channel select applied on
Save while "Check again" ran immediately against the still-saved channel,
so picking Nightly and checking reported "latest version" for Stable under
a select reading Nightly. The status now carries a badge naming the channel
the verdict describes; while the select shows an unsaved other channel the
verdict is dimmed, a hint names both channels, and the check button becomes
"Save and check for <channel> updates", which submits the form — the main
process already re-checks when the saved channel changes. A download in
flight or finished belongs to the previous channel and keeps the plain
check.

"What's new" for a nightly published after the app started failed with a
raw IPC error: each release catalog is a process-lifetime snapshot and a
fully paged list never re-read GitHub. findIndex now reloads the catalog
once when a version is missing, and a newly found update drops every
catalog. The dialog recognises the not-found rejection through the shared
marker text, explains it with the version, and links to the channel's
release list; other failures keep their reason under a localized headline.

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

* fix(updater): serialize readers of one release catalog

findIndex may rebuild the shared release array while another reader of
the same catalog still holds an index into the old one and dereferences
it after paging further. Every reader now runs through the catalog's
runExclusive queue (getReleaseNotes and the manual-update check), so a
reload can no longer pull the list out from under a navigation.

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

* fix(settings): attribute a kept download to the channel it was found on

setChannel keeps a download that is running or finished when the saved
channel changes, but status.channel already names the new channel, so the
About badge attributed a Stable download to Nightly and the pending hint
vanished. Every check now stamps status.verdictChannel with the channel it
ran on and setChannel leaves it alone; the badge names that channel, and
while it differs from the saved one a hint says the shown update came from
the other channel and the saved one has not been checked yet.

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

* refactor(updater): move release-notes reads out of AppUpdateService

AppUpdateReleaseCatalogs (app-update-release-notes.ts) now owns the
per-channel catalogs and both reads the updater performs on them: release
notes with previous/next paging and the newest release for the
manual-install fallback. The service only delegates, shrinking from 610
to 508 lines instead of growing.

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

* docs(updater): name verdictChannel as the badge's source

The About paragraph still said the badge reads status.channel while the
paragraph below it and the code use status.verdictChannel.

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

* fix(settings): show the release list, not the earlier release, after a paging failure

A failed Previous/Next keeps the earlier notes for navigation while the
body shows the error, so the dialog's action offered the earlier release
instead of the channel release list. The error is now checked first.

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

* fix(updater): do not reload the catalog before falling back to latest

A read that falls back to the newest release on a miss (the installed
version's notes, e.g. an unpublished local build) paged the whole list
twice: findIndex reloaded on the miss before index 0 was selected. The
reload is now opt-in per call and off on that path.

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

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-19 13:09:24 +02:00
4gray c0e9cd5de3 fix(settings): show current release notes (#1101)
* fix(settings): show current release notes

* fix(updater): use app version for local release notes

* fix(settings): constrain release note images

* fix(settings): prefer current notes without updates
2026-06-29 11:03:15 +02:00
4gray b1119189e2 feat(updater): add GitHub releases desktop updater
Adds the GitHub Releases desktop updater with release notes, startup notification, packaging metadata, tests, and CI fixes for Electron E2E.
2026-06-28 22:21:20 +02:00