The dropdown was in the HTML all along and still could not be seen. Three separate causes, found by measuring the rendered element rather than trusting that the markup existed: 1. Clipped off-screen. The h1 is a flex row with no wrap. Measured at an 800px viewport: the language span started at x=620 and ended at x=810, past the viewport edge, so only its first few pixels were painted. The project badge alone took 309px. Adding flex-shrink and truncating the badge did not fix it - there is genuinely no room in that row. The selector now gets its own bar directly under the header, and the project name ellipsises. Verified visible: x=181, right=341 in an 800px viewport, 34px tall. 2. Empty on every other page. base.html rendered the select from a `languages` variable that almost no page supplies, so the login page and the rest of the app showed a 38px-wide dropdown with zero options - effectively invisible, and a dead control. Pages now opt in by overriding a header_bar block. Verified /, /speakers, /chapters-audio and /login all still render. 3. Browser cache made my own screenshot lie. It showed a stale Japanese string containing the word "decisiveness" that is in no file on disk. A cache-busted fetch confirmed the server is clean. Worth remembering: a screenshot taken through a warm cache is not evidence. The screenshot also exposed a data bug. All 12 sample utterances carried type "narration" - including Kainda, Duchess Victoria, Deal Hunter, Nanny and Trader Romano, who are all speaking. Every row rendered a narration badge and the file told UmbraTrans that six characters were not speaking. SHAPE in build_sample_translations.py now marks 6 dialogue / 6 narration, and the generated JSONs are regenerated to match. Also removed a misleading issue. It reported "12 rendered clips have no staleness marker" as a translation problem; the markers are absent because render_lang_test.py does not write them, so it was sending the reader after a defect that does not exist. Replaced with the honest one: only 12 of 4,319 translated and none confirmed - sample only, not publishable. Suite: 721 passed, 8 pre-existing. ruff clean on changed regions.
Deal Hunter sample chapter - translated
Sample chapter 1 (the voice-introduction sample) in all 10 languages
Qwen3-TTS produces. Files are named <base>_<LANG>.json.
These are LLM-produced samples from a single pass. They are not the multi-pass semantic translation the production pipeline is meant to do (see specs/27-translation-pipeline-multipass.md). They exist to evaluate the audio stage per language and to agree the file format early. Native-speaker review required.
Register
Casual/informal register throughout, matching the English source. Korean uses 해요체 (everyday polite), NOT 합쇼체 (formal written) and NOT 해체 (반말, which would be socially wrong between these characters). T/V languages use the informal form (du/tu/tú). Russian keeps вы, because ты is too intimate for narration. Japanese stays polite-but-warm.
Files
deal_hunter_sample_ch1_DE.jsondeal_hunter_sample_ch1_EN.jsondeal_hunter_sample_ch1_ES.jsondeal_hunter_sample_ch1_FR.jsondeal_hunter_sample_ch1_IT.jsondeal_hunter_sample_ch1_JA.jsondeal_hunter_sample_ch1_KO.jsondeal_hunter_sample_ch1_PT.jsondeal_hunter_sample_ch1_RU.jsondeal_hunter_sample_ch1_ZH.json
Source issues found while translating
- utt 3: 'Kianda's aunt' — 'Kianda' is a typo for 'Kainda'.
- utt 5: 'the AI the runs the ship' — 'the' should be 'that'.
- utt 8: 'I trade salvage' — double space.
- The narrator's cues are telegraphic ('Princess Kainda say hello'), which a translator has to resolve by guessing. The production pipeline should decide whether to normalise these at the source.
- Every utterance in this chapter is typed 'narration' even where a character speaks in the first person. Same class of finding as the speaker-review audit; it matters because emotion and pace are set per utterance.
Decisions to confirm
Deal HunterandUmbra Audiokept in English in every language. Deal Hunter is both the title and the ship AI's name, so translating it would break the referent inside the story. Localisation decision, yours.- Character names transliterated by sound, not translated by meaning.