Skip to content

Releases: fukuyori/Spindle

0.7.3

Choose a tag to compare

@fukuyori fukuyori released this 29 Jul 01:48

[0.7.1] - 2026-07-28

Fixed

  • Glossary terms now reliably reach the model. The glossary is sent inside
    the user-turn task statement as well as the system prompt (translation-tuned
    models weigh the former), reworded per task (translation vs. summary), and
    emitted as one terse line instead of an instruction paragraph. The term list
    is capped relative to the text length so a large glossary can no longer
    drown a short paragraph and derail the translation.
  • Glossary matching misses fewer occurrences. Terms whose edges are CJK
    characters match inside unspaced Japanese/Chinese prose (the word-boundary
    guard no longer applies there), and English entries also match simple
    plural/possessive forms ("Caesars", "Caesar's").
  • Blocks that are exactly one glossary term skip the model. Headings such
    as a bare person's name are rendered directly with the glossary target — in
    page translation, selection translation, and EPUB export — instead of
    risking a model round-trip mangling the mandated form.

0.7.0

Choose a tag to compare

@fukuyori fukuyori released this 19 Jul 00:10

[0.7.0] - 2026-07-19

Added

  • Bilingual UI (Japanese / English). All menu, toolbar, dialog, and status
    strings are now translatable. The UI language follows the system locale
    (Japanese system → Japanese UI, anything else → English) and can be forced
    via the new 表示 → 言語 / Language menu (applied after restart). Source
    strings remain Japanese; the English catalog lives in i18n/spindle_en.ts
    (refresh with the update_translations CMake target, compiled into the
    binary by lrelease at build time).

0.6.6

Choose a tag to compare

@fukuyori fukuyori released this 18 Jul 23:40

[0.6.6] - 2026-07-19

Fixed

  • Facing pages meet cleanly at the spine. Each page of a spread now
    edge-aligns toward the center instead of centering in its own half, the 2px
    seam between the two views is gone, and the page-fit measurement no longer
    loses the width of the pre-fit scrollbar — which had left a theme-colored
    strip at the spine.
  • Page turns can no longer leave pages unscaled. Navigating quickly could
    occasionally skip the reader-script injection, showing the raw page at
    natural size with scrollbars. The injected-script collections are now only
    rewritten when their content actually changes, and every finished load
    verifies the fixed-layout fit, re-injecting the script if it never ran.
  • Backward navigation keeps the established spread pairing. Spread pairs
    are anchored at the front of the book, so stepping back from a lone final
    page rejoins the canonical pairs instead of shifting every spread by one.
  • Arrow keys follow the reading direction on fixed-layout pages. In
    right-bound books ← advances and → goes back, matching the edge-click
    mapping.

0.6.5

Choose a tag to compare

@fukuyori fukuyori released this 18 Jul 12:05

[0.6.5] - 2026-07-18

Changed

  • The selection-translation popup closes on any click outside it. Clicks
    landing on the reading view (a native child window invisible to the popup's
    mouse grab) previously left the popup open; only clicking outside the app
    window or pressing Escape dismissed it.

Fixed

  • Selection translation works in fixed-layout books. The facing-page
    spread view was created after the web channel was wired up, so selections on
    the companion page could never reach the app — no menu appeared. The
    companion page now connects to the bridge; selecting text there opens the
    text-action menu (翻訳 / 要約 / コピー / Web で検索). Highlight colors and
    notes are offered only on the primary page, where the selection can be
    anchored to the current chapter.

0.6.3

Choose a tag to compare

@fukuyori fukuyori released this 18 Jul 04:24

[0.6.3] - 2026-07-18

Added

  • Fixed-layout EPUBs can be read as facing-page spreads. The new
    表示 → 固定レイアウトを見開き表示 option is enabled by default and honors
    the book's left/right page-progression direction plus page-spread-*
    placement metadata. Clicking the outer 15% of either page also turns the
    spread in the corresponding physical direction. The first spine page is
    always treated as a cover and shown alone. Binding direction can be set to
    automatic, right-bound, or left-bound; automatic uses right binding for
    vertical writing and otherwise follows the EPUB.

Fixed

  • Fixed-layout arrow navigation turns the page on the first key press.
    Left/Right are intercepted before Chromium can use the first press to
    horizontally scroll an oversized page. The complete fixed page is fitted to
    the reading pane while retaining its authored aspect ratio. Books that omit
    rendition:layout are also recognized when every spine document is exactly
    one image page with no surrounding text.
  • Single-image chapters now always open fitted to the reading pane. The
    source image's aspect ratio determines whether its width or height meets the
    window edge, independently of the retained text zoom. Image zoom and mouse
    drag panning now use the image's actual bounds, avoiding scrollable empty
    space on the non-overflowing axis.
  • Book-search results now jump to the selected occurrence. Repeated matches
    in the same chapter use their stored text offsets instead of always opening
    Chromium's first match. Pressing Enter in the search field opens the first
    result immediately.

0.6.2

Choose a tag to compare

@fukuyori fukuyori released this 14 Jul 22:42

[0.6.2] - 2026-07-15

Added

  • Configurable line wrapping. 表示 > 折り返し設定… can keep text fitted to
    the window or limit each line to a chosen 10–120 character measure (initially
    40). The setting is saved across launches and also works with vertical writing.

0.6.1

Choose a tag to compare

@fukuyori fukuyori released this 13 Jul 19:31

[0.6.1] - 2026-07-14

Fixed

  • Glossary extraction no longer times out when a model keeps generating
    malformed JSON.
    Responses now use a strict schema and a bounded output
    length, so a runaway model cannot occupy Ollama until the five-minute
    request timeout.

0.6.0

Choose a tag to compare

@fukuyori fukuyori released this 13 Jul 18:51

[0.6.0] - 2026-07-14

Added

  • Glossary generation (用語集を生成). 翻訳 > 用語集を生成… extracts proper
    nouns and recurring terms from the current chapter or the whole book with
    Ollama (JSON-forced output, summary model) and writes their target-language
    wordings into <book>.glossary.json, merging with any existing entries
    (existing ones win). Extracted terms are kept only if they actually occur in
    the scanned text; progress dialog with cancel (cancel keeps the terms found
    so far), and the updated glossary applies to translations and summaries
    immediately.

0.5.2

Choose a tag to compare

@fukuyori fukuyori released this 12 Jul 13:03

[0.5.2] - 2026-07-12

Added

  • Audio-file export (章を音声ファイルへ書き出し). The 読み上げ menu can
    render the current chapter to a single audio file using the same voices and
    原文/訳文 rule as playback, with a progress dialog and cancel. Blocks
    synthesized by different engines/sample rates (VOICEVOX 24 kHz, Piper
    22.05 kHz, OS voices) are resampled into one stream with a 300 ms pause
    between paragraphs. OS voices are used via QTextToSpeech's synthesize
    capability where the engine supports it; VOICEVOX and Piper always support
    export. WAV (16-bit mono) is written directly; MP3 / M4A are encoded
    through ffmpeg (auto-detected on PATH, or set 読み上げ > 音声設定 >
    ffmpeg) — MP3 at ~130 kbps VBR (-q:a 4), M4A as 96 kbps AAC.

[0.5.1] - 2026-07-12

Added

  • Local AI voices for read-aloud: VOICEVOX and Piper. Besides the OS
    voices, the voice pickers list the speakers of a running
    VOICEVOX server (VOICEVOX: 四国めたん (ノーマル), Japanese) and the .onnx voice models of a local
    Piper install (Piper: en_US-lessac-medium, multi-language). Picking a prefixed voice routes that
    language to that engine — so e.g. Japanese can be spoken by VOICEVOX while
    English in the same book falls back to an OS voice. The VOICEVOX endpoint
    (default http://localhost:50021) and the Piper executable / voices folder
    are set in 読み上げ > 音声設定. Speech rate maps to VOICEVOX speedScale /
    Piper --length_scale; synthesized audio plays through Qt Multimedia (the
    engines are built only when that module is present).

[0.5.0] - 2026-07-12

Added

  • Read-aloud (読み上げ). The current chapter can be spoken block by block
    with the OS speech voices (Qt TextToSpeech; WinRT/SAPI on Windows,
    AVSpeechSynthesizer on macOS, speech-dispatcher on Linux). Reading follows
    the translation display mode — 原文 and 対訳 read the source text, 訳文
    reads the translation (falling back to the source where none is cached
    yet) — with the voice matched to the spoken language. The spoken paragraph
    is tinted and auto-scrolled into view,
    <ruby> text is spoken as its <rt> reading instead of base + furigana
    concatenated, reading starts from the paragraph currently on screen, and the
    chapter end can auto-advance into the next chapter (読み上げ menu toggle).
    Speech rate and a per-language voice are configurable in 読み上げ > 音声設定;
    play/pause/stop live on the toolbar and in the new 読み上げ menu
    (Ctrl+Shift+S toggles). Builds without Qt TextToSpeech still compile, with
    the actions reporting that no speech engine is available.

0.4.5

Choose a tag to compare

@fukuyori fukuyori released this 12 Jul 10:02

[0.4.5] - 2026-07-12

Added

  • Bare-text chapters are now translatable. Some EPUBs (often converted
    ones, e.g. Aozora/Gutenberg conversions) carry chapter prose as bare text
    directly inside <div>/<body>, separated by <br/><br/> instead of
    <p> elements. Such text had no block structure, so translation,
    highlighting, search jumps, and Kindle-note matching only saw the headings.
    Chapters are now normalized on load: each run of bare inline text becomes a
    synthetic paragraph (split at 2+ consecutive <br>, spacing preserved),
    consistently across the reading view, sidecar caches, and translated-EPUB
    export.
  • Wrong-language translations are caught. When the model answers in a
    language whose script clearly doesn't match the target (e.g. Chinese
    returned for a Japanese target), the request is retried once with a
    stronger instruction; if it still doesn't comply the paragraph shows an
    error instead of caching the wrong text.

Fixed

  • Chinese ⇄ Japanese translation reliability. The translation prompt
    told the model to return text "already in the target language" unchanged,
    which made kanji-heavy Japanese pass through untranslated with a Chinese
    target (and vice versa) — and the untranslated result was then cached.
    The prompt now states the task in the user turn in a form that
    translation-tuned models (e.g. TranslateGemma) also follow, and no longer
    offers the pass-through escape hatch.
  • Reasoning models' chain of thought leaked into translations. Content
    ending with a </think> marker (e.g. Qwen3 with thinking nominally
    disabled) now has everything before the marker stripped.