Fix synced transcript auto-scroll for non-Latin transcripts (CJK, Thai, Hindi, Arabic, and more) - #5494
Conversation
Japanese (and other CJK) transcripts end sentences with 。!? and use 」』 quotes, none of which were in the sentence-splitting punctuation lists. So joinSplitSentences() never split a CJK transcript and collapsed it into a single TranscriptEntry, leaving the synced "follow along" auto-scroll with no per-line anchor — it stayed pinned to the top while only the highlighted word advanced. Recognise CJK sentence terminators and closing brackets so CJK transcripts split per sentence again and the auto-scroll can anchor each line. PCDROID-639
|
Claude finished @joashrajin's task in 1m 59s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Overall this is a well-targeted, low-risk fix with a clear root-cause writeup and strong test coverage. The change is purely additive to two punctuation lists, and the new characters are A few observations, none blocking: 1. CHANGELOG entry is checked off but missing (should fix)The PR checklist marks "I have added an entry in CHANGELOG.md" as done, but the diff only touches the two transcript files — there's no CHANGELOG change. This is a user-facing bug fix, so it warrants an entry. 2. Cross-product produces spurious mixed-locale combos (minor / cosmetic)
3.
|
- Don't inject an ASCII space when joining adjacent CJK fragments, so a multi-cue Japanese sentence renders without spurious gaps between characters. - Treat CJK closing marks (」』)) as sentence-ending only as terminal combos (。」, !」, …) rather than bare, so a mid-sentence quoted term like 「AI」 sitting at a cue boundary no longer splits the sentence. - Recognise half/full-width full stops 。 and . as terminators. - Single-source the CJK terminator/closer sets and add tests for the no-space join, terminal-combo splitting, the bare-closer case, and CJK timing/offsets. PCDROID-639
|
Claude finished @joashrajin's task in 2m 37s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Re-reviewed after the latest commits. Since my first pass the PR has addressed every actionable point: the CHANGELOG entry is now present, and the cosmetic CJK space-joining issue I'd flagged as the top follow-up has been fixed directly via What's good
Minor / non-blocking (left as inline comments)
Testing noteI couldn't execute Verdict: Correct, well-tested, and responsive to prior feedback. No blocking issues — the three inline notes are optional polish/follow-ups. |
- Suppress the join space whenever either side of a boundary is CJK (not only when both are), so no stray space hugs a CJK closing mark (「AI」, not 「AI 」). - Inspect boundary code points so supplementary-plane ideographs (CJK Ext B+, encoded as surrogate pairs) are recognised. - Build the mid-sentence quotation combos per script (Latin x Latin, CJK x CJK) instead of a full cross-product, dropping the impossible mixed-locale pairs. PCDROID-639
|
Claude finished @joashrajin's task in 1m 56s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Re-reviewed after the latest push ( Prior feedback — now resolved
What's correct in the current state
Non-blocking observations (no change required)
Testing
Verdict: Correct, well-tested, and fully responsive to prior feedback. No blocking issues. |
A Japanese sentence can be wrapped in ASCII / curly quotes (彼は"はい。") and English can appear in CJK brackets (「OK.」), so terminator + closer sentence boundaries cross scripts. Build the terminal-combo set as the full terminator x closer cross-product across both scripts (not same-script only), so findMidSentence keeps the closing quote with its sentence instead of splitting before it. PCDROID-639
|
Claude finished @joashrajin's task in 1m 46s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Re-reviewed after the latest push. This commit reverses an earlier decision (the previous round had split combos into same-script-only, What's correct in the current state
One trade-off worth a conscious note (non-blocking)Broadening the combo set slightly widens the already-documented "nested quoted speech" degradation. Adding Carried-forward items (all still reasonable)
Testing
Verdict: Correct, well-tested, and the mixed-script broadening is justified. No blocking issues; the nested-quote trade-off is the only thing worth a deliberate ack. |
|
Claude finished @joashrajin's task in 1m 31s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Re-reviewed at Correctness — verified by trace-through
Non-blocking notes (no change required)
Testing
Verdict: Correct, well-tested, and fully responsive to prior feedback. No blocking issues. |
…ynced-transcript-auto-scroll-jumps-back-to-top-of # Conflicts: # CHANGELOG.md
|
Claude finished @joashrajin's task in 1m 30s —— View job Code Review — PR #5494: CJK transcript auto-scroll fix
Re-reviewed after the latest sync ( Correctness — holds up under trace-through
Non-blocking notes (no change required — consistent with prior rounds)
Testing
Verdict: Correct, well-tested, and fully responsive to the prior review rounds. No blocking issues. |
… transcripts - Add sentence terminators for Arabic (؟), Urdu (۔), Devanagari (। ॥), Burmese (။), Khmer (។ ៕), Ethiopic (።), and Armenian (։) so those transcripts split into per-sentence entries for auto-scroll anchoring. - Cap the phrase accumulator: scripts with no sentence-final punctuation (Thai) and unpunctuated auto-generated captions can never match a terminator, so flush at the cue boundary once the accumulated phrase outgrows a sentence-sized length. Every transcript now yields multiple scrollable entries regardless of script. - Extend the no-space join rule to all space-less scripts (Thai, Lao, Khmer, Burmese) instead of CJK only. - Extract flushAccumulatedPhrase() so the forced flush, sentence flush, and trailing flush share one implementation.
|
Claude finished @joashrajin's task in 3m 23s —— View job Code Review — PR #5494 (synchronize)Re-reviewed after the new commit
This commit generalises the PCDROID-639 fix from CJK to every script — and, importantly, to scripts and captions that have no sentence-final punctuation at all. It's the logical completion of the fix: the root cause was "one giant What's correct — verified by trace-through
Non-blocking observations
Testing
Verdict: Correct, well-tested, and a sensible generalisation of the original fix. No blocking issues; the accumulator-cap behaviour change (note 1) is the only item worth a deliberate ack. |
|
Version |
Description
The synced ("follow along") transcript never kept the highlighted line anchored for Japanese (CJK) transcripts: each time playback advanced to the next line, the transcript scrolled back to the top, so the user had to manually scroll down to find where playback was. It reproduced only with CJK text, not with Latin-text transcripts.
Root cause: the synced-transcript post-processing (
TranscripSanitization.joinSplitSentences()) splits a transcript into per-sentenceTranscriptEntryblocks usingendsAsSentence()/findMidSentence(), whose punctuation lists were Latin-only (. ! ? … - ) ] > } " ” ' ’). Japanese sentences end with。!?, so no cue was ever treated as a sentence boundary and the whole transcript collapsed into a singleTranscriptEntry. With one entry,AutoScrollEffect(which anchors the scroll onhighlightState.entryIndex) had no per-line target: the index stayed at0, so the list stayed pinned to the top while only the highlighted word advanced.Changes:
。!?(and half/full-width full stops。.) so CJK transcripts split into per-sentence entries again, restoring per-line auto-scroll anchoring.」』)as sentence-ending only as terminal combos (。」,!」, …), never bare — a bare closing quote also wraps a mid-sentence quoted term (これは「AI」について話します。), which must keep accumulating rather than split.これはペンです。, notこれは ペンです。).Extended to other non-Latin scripts (follow-up commits in this PR — the same root cause affected every script the punctuation list didn't know about):
؟), Urdu (۔), Devanagari/Hindi (।॥), Burmese (။), Khmer (។៕), Ethiopic (።), and Armenian (։).Pure-Latin transcripts are unaffected — the new punctuation is
endsWith-matched and can't appear at the end of Latin text, and the accumulator cap only triggers where no sentence boundary was found for 160+ characters (punctuated text flushes on terminators long before that).Fixes PCDROID-639
Out of scope / follow-ups (from review)
TranscriptWindowExtractor.windowText()gates onsplit("\s+").size >= MIN_WORDS; CJK has no whitespace, so AI bookmark/summary enrichment silently returns nothing for Japanese podcasts. Pre-existing, separate feature; not addressed here.findMidSentence()prefers a terminator+quote combo over a later bare terminator, so彼は「はい。」と答えた。それから帰ったsplits at the inner。」rather than the true outer。. Leftover is preserved (degraded, not lost). Mirrors the existing Latin quotation-first heuristic.」 』 )are covered; lenticular/angle brackets (】 》 〉etc.) used in some Japanese headings are not yet recognised as terminal-combo closers.java.text.BreakIterator.getSentenceInstance(Locale)could replace it locale-aware, but isn't a clean drop-in given the surrounding split/timing/offset logic.compactWhiteSpace()doesn't normalise the ideographic space(cosmetic, pre-existing).Testing Instructions
Automated:
./gradlew :modules:services:repositories:testDebugUnitTest --tests "*TranscriptSanitizationTest*"— 114 tests, 0 failures (includes the CJK cases, the new-script terminators, the Thai/unpunctuated cue-boundary flush, and the Thai/Devanagari spacing cases).On device (see the before/after recordings below):
synced_transcriptsenabled and a Plus account, play an episode of a Japanese-language podcast that has a synced transcript — e.g. EASY JAPANESE PODCAST (podcast UUID08b59600-4245-0139-3351-0acc26574db2).Latin transcripts are unaffected (covered by the existing Latin unit tests; the new punctuation can't match Latin text).
Screenshots or Screencast
Before:
Screen_Recording_20260630_135738_Pocket.Casts.mp4
After:
Screen_Recording_20260630_203717_Pocket.Debug.mp4
Checklist
./gradlew spotlessApplyto automatically apply formatting/linting)modules/services/localization/src/main/res/values/strings.xmlI have tested any UI changes...