Skip to content

feat: per-book language for read-aloud voices and hyphenation (stacked on #302, refs #286) - #303

Merged
van-geaux merged 4 commits into
van-geaux:mainfrom
chortya:up/feat-epub-book-language
Oct 23, 2026
Merged

van-geaux merged 4 commits into
van-geaux:mainfrom
chortya:up/feat-epub-book-language

Conversation

@chortya

@chortya chortya commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Contribution pause

The maintainer lifted the pause and invited split PRs in #286.

Summary

Read-aloud only offers voices for the EPUB's declared language. Books with a wrong or missing dc:language (common in converted files) therefore got the wrong voice list, e.g. only Dutch voices for an English book, and the wrong hyphenation patterns.

  • In-book options → This book → Book language: Auto (shows the source: book or device) or any installed language, chosen from a dialog with a lazy list.
  • An override goes to the EPUB navigator (language, for hyphenation) and the read-aloud navigator (AndroidTtsPreferences.language, which selects the voice list). Both apply live, even while speaking. A change made while read-aloud is still preparing is applied once its navigator exists.
  • Readium only injects language into documents whose <html> declares none, so the reader's existing current-document bridge also sets an override on <html>/<body> (lang and xml:lang) and restores the publisher's values on Auto.
  • In Auto, a declared book language is left to Readium (so per-element xml:lang still works), and read-aloud keeps Readium's own choice.
  • Remembered per book (readium_epub_book_languages, keyed by reader key, not written in Preview, cleared on logout).

Verification

  • ./gradlew :app:testDebugUnitTest — 961/961 pass (new EpubBookLanguageTest: resolution order, navigator/TTS language rules, store, document-language script). :app:lintDebug — 0 errors. :app:assembleDebug succeeds. No added trailing whitespace; line endings preserved.
  • Connected, Pixel Fold API 36 emulator:
    • New EpubBookLanguageInstrumentedTest 5/5 — read-aloud offers the book language's voices by default and the override's voices live; read-aloud starts in the override language; a change during read-aloud preparation is applied; the page language follows the override live and is remembered per book; a chapter that declares its own lang/xml:lang takes the override and gets its own value back on Auto (this test fails without the fix below).
    • EpubReaderOptionsOverlayInstrumentedTest 5/10 (the new book-language option test passes; the same 5 fail on main on this emulator). ReadiumEpubOpenInstrumentedTest 16/18 and EpubMediaOverlayControlsInstrumentedTest 3/4 — same failures as on main on this emulator.
  • Device: the fork build is used on a Galaxy Z Fold8. This branch itself was run only on the emulator.
  • Peer review (Codex GPT-6-Astra) found that Readium 3.0.2's injectLang keeps a chapter's own lang/xml:lang, so the override did not reach hyphenation in such books. Fixed as above; the re-review found no remaining issues.

🤖 Generated with Claude Code

@van-geaux

Copy link
Copy Markdown
Owner

Thanks @chortya, the per-book language implementation and tests look good. As this PR is stacked on #302, please rebase it after #302 is merged and resolve the remaining conflicts. Once the branch is updated and CI is green again, it should be ready to merge.

@chortya
chortya force-pushed the up/feat-epub-book-language branch from 6474052 to b76a3d2 Compare October 21, 2026 14:50
@chortya

chortya commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the updated #302 for now, so CI is green. I'll rebase it onto main once #302 is merged.

@van-geaux

van-geaux commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Thanks @chortya, the language picker and live voice switching look really good.

When you rebase, could you also make sure a book’s language choice stays separate between different servers or accounts? I could see the same book ID on another server picking up the old choice.

chortya and others added 4 commits October 23, 2026 06:52
Readium picks one read-aloud language (book metadata, else the device
locale) and lists only its voices, with no way to change it; the
hyphenation fallback made the same assumption. Adds a Book language
setting to the in-book options (This book): Auto shows whether it comes
from the book or the device, and an override is remembered per book,
sent to the EPUB navigator for hyphenation and to the read-aloud
navigator for voices, and applied live during playback.

Tests: JVM resolution and option rules; on-device voice lists with the
system speech engine (Auto, live switch, start in override), page
language and persistence across recreation, and the picker UI.

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

- A book-language (or voice setting) change made while read-aloud is
  preparing is applied once the navigator exists.
- The book-language picker is a dialog with a lazy list instead of a menu
  composing ~200 items.

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

Readium only injects its language into documents whose <html> declares
none. The current-document bridge now also sets the override on <html>
and <body> (lang and xml:lang) and restores the publisher's values on
Auto, so hyphenation follows the chosen language in every chapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The same book ID can exist on another server or account, so the per-book
language override is now keyed by the active server profile (the boundary
van-geaux#309 uses for downloads and snapshots) as well as the reader key.

Choices now survive switching profiles instead of being wiped for every
profile. Signing out clears only the signed-out profile's choices, for
BookOrbit, Kavita and Komga alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chortya
chortya force-pushed the up/feat-epub-book-language branch from b76a3d2 to 4fc8250 Compare October 23, 2026 08:21
@chortya

chortya commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, good catch. Rebased onto current main (with #302 and #309) and fixed in 4fc8250:

  • The book language choice is now keyed by the active server profile as well as the book, using the same ServerProfileStore.activeId() boundary fix: isolate multiple profiles on the same server #309 uses for downloads and snapshots. The same book ID on another server or account no longer sees it.
  • Switching profiles keeps each profile's choices. Before, they were wiped for every profile on each switch.
  • Signing out clears only the signed-out profile's choices. This now also covers Kavita and Komga, whose sign-out didn't clear them before.

Tests: EpubBookLanguageTest checks the per-profile keys, and EpubBookLanguageInstrumentedTest.choicesStaySeparateBetweenProfilesAndSignOutClearsOnlyItsOwn checks that two profiles keep separate choices and clearing one leaves the other. All 6 tests in that class pass on a Pixel Fold emulator; CI is green.

@van-geaux
van-geaux merged commit 759bb5c into van-geaux:main Oct 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants