* feat(wordlens): support en-en monolingual glosses
Gloss difficult English words with a short English definition for learners
reading English with English hints.
- build: buildEnEn + shortDefGloss read ECDICT's English `definition` column
(first/primary WordNet sense, POS-stripped, drop ;-example, <=24 word-boundary
with trailing-connector trim). New `en-en` CLI branch; buildEnZh/buildEnEn now
share a buildEnPack core.
- gating: drop the hardcoded `hint === source` rejections (wordlensSection,
WordLensPanel) so same-language packs are allowed; availability is decided by
the manifest (resolvePack returns null when no pack exists).
- data: data/wordlens/en-en.json (26,578 entries) + regenerated manifest.json.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(wordlens): gloss styling, derivation lemmas, display-time cap
Builds on the en-en monolingual gloss support with refinements and
regenerated packs.
- settings: per-book gloss <rt> font size (em) and color in
Settings > Language > Word Lens (getRubyStyles reads viewSettings).
- en-en hints: WordNet hybrid (a simpler synonym, else a category
hypernym, else the ECDICT definition) instead of raw verbose
definitions.
- lemmatization: gate difficulty by the lemma rank for every English
source pair. enBaseFormCandidates now also covers -able/-ible suffixes
and negative prefixes (un/in/im/ir/il), so insufferable resolves to
suffer. A candidate is accepted when the English definition names the
base OR the Chinese translations share a content character, which keeps
true derivations (insufferable -> suffer) and rejects coincidental
stems (capable -> cap). en-X packs inherit the en-en lemma table.
- display cap: the max gloss length is applied at render time in
cleanGloss (MAX_GLOSS_LEN), so the packs store the full hint and the
cap can change without regenerating data.
- tooling: pnpm wordlens:preview to sample pack entries; cache build
corpora under data/wordlens/.sources (gitignored).
- data: regenerate en-en, en-zh and en-de/es/fr/pt/ru plus the manifest.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"Word Wise" is a Kindle trademark, so rename the inline-gloss feature to
"Word Lens" throughout the product.
- User-facing strings → "Word Lens" across all 34 locales; brand translated
for Chinese (zh-CN 单词透镜, zh-TW 單詞透鏡) and German (Word-Lens-Daten).
- Code identifiers: WordWise→WordLens, wordWise→wordLens, WORD_WISE→WORD_LENS.
- Files/dirs: src/services/wordwise→wordlens, WordWisePanel→WordLensPanel,
wordwise{Ruby,Section}.ts, build/sync scripts, test dirs/fixtures,
data/wordwise→data/wordlens.
- Storage paths: CDN base, R2 key, on-device cache dir, WORDLENS_R2_BUCKET env,
pnpm wordlens:{manifest,sync}. manifest.json is path-agnostic so its
sha256/bytes stay valid (verified).
- biome.json: point the formatter-ignore at data/wordlens so the generated
one-line gloss packs aren't pretty-printed on commit.
Migration notes:
- Re-run `pnpm wordlens:sync` to upload packs to cdn.readest.com/wordlens/.
- Persisted view-settings keys renamed (wordWiseEnabled/Level/HintLang and
wordWiseAutoDownload) — saved values reset to defaults once on upgrade.
- Cached packs under the old Data/wordwise/ orphan (harmless re-download).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(reader): Word Wise — inline native-language vocabulary hints
Kindle-style Word Wise: a short native-language gloss renders above difficult words
as you read (always-on ruby), gated by a CEFR vocabulary-level slider (A1–C2);
tapping a glossed word opens the existing dictionary.
- Pipeline: CEFR→frequency-rank difficulty, inflection-aware gloss index, pure
offset-aware planner (EN regex + jieba for CJK).
- Rendering: <ruby cfi-skip>…<rt cfi-inert> injected per occurrence — CFI-transparent
(verified), so highlights/bookmarks/progress are unaffected; kept out of TTS word
offsets and find-in-book.
- Delivery: gloss packs are version-controlled in data/wordwise/, mirrored to R2, and
downloaded on demand into local storage (sha-verified, single-flight) when enabled.
- Settings: a Word Wise sub-page under Settings → Language (enable, level, hint
language, per-pack download/manage, auto-download toggle).
- Build tooling: scripts/build-wordwise-data.mjs (ECDICT / CC-CEDICT+HSK / WikDict +
FrequencyWords, with lemmatization) and scripts/sync-wordwise-r2.mjs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* data(wordwise): bundled gloss packs + manifest + attribution
13 frequency-trimmed gloss packs (en↔中文 + es/fr/de/pt/it/ru↔en, ~19 MB) generated
by build-wordwise-data.mjs from ECDICT (MIT), CC-CEDICT + HSK, and WikDict +
FrequencyWords (CC-BY-SA). Source of truth, mirrored to the CDN via `pnpm wordwise:sync`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>