From 2f4c8529e968bb03e858524c2e5f67b4e9966bf4 Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Sun, 4 Oct 2026 18:58:14 +0200 Subject: [PATCH] fix(i18n): remove duplicate keys and dead frontend branches Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 1 + static/js/audiobook-preview-export.js | 30 --------------------------- static/js/i18n.js | 28 ++++++++++++------------- static/js/library-characters.js | 2 +- static/js/magazine.js | 2 +- 5 files changed, 17 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 858f67b..a022ae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi - **Voice list rows no longer show the "Source unknown" badge** (it crowded the play buttons). The badge stays in the voice inspector, next to the Source & consent panel. ### Fixed +- **Duplicate German i18n keys and dead frontend code.** Removed 14 shadowed duplicate keys in `i18n.js` (effective translations unchanged), the unreachable body of `audiobookShowPreview`, and two identical-branch ternaries. - **Security hardening (Sonar findings).** The Docker installer downloads `get-docker.sh` into a private `mkdtemp` dir (not a predictable `/tmp` path) and removes it afterwards; the OMDb poster lookup uses HTTPS; the fish.audio cache key marks MD5 as `usedforsecurity=False`. - **Background jobs could be garbage-collected mid-run.** Fire-and-forget `asyncio.create_task` calls (magazine, conversation, tts, stt, library, sources) now go through `core.tasks.spawn`, which keeps a strong reference until the task ends and logs failures by exception class only. - **Voice archetype gallery broke `npm run check:frontend`**: its `say` helper collided with `magazine.js`; renamed to `archSay`. diff --git a/static/js/audiobook-preview-export.js b/static/js/audiobook-preview-export.js index 3110343..36f4535 100644 --- a/static/js/audiobook-preview-export.js +++ b/static/js/audiobook-preview-export.js @@ -56,36 +56,6 @@ async function audiobookOpenCurrentInRehearser() { function audiobookShowPreview() { audiobookOpenCurrentInRehearser(); - return; - const segs = _audiobook.segments || []; - const roster = _audiobook.roster || []; - document.getElementById('audiobook-preview')?.remove(); - const ov = document.createElement('div'); - ov.id = 'audiobook-preview'; - ov.className = 'audiobook-overlay'; - // datalist = Narrator + LLM roster + any speakers present in the segments (incl. Unknown) - const speakerSet = [...new Set(['Narrator', ...roster, ...segs.filter(s => s.type === 'dialogue' && s.speaker).map(s => s.speaker)])]; - const charCount = speakerSet.filter(n => !/^Unknown|Unbekannt/i.test(n)).length; - const opts = speakerSet.map(n => `