Skip to content

Add grammar check via LanguageTool - #12831

Open
ivandrofly wants to merge 1 commit into
SubtitleEdit:mainfrom
ivandrofly:grammar-check-languagetool
Open

Add grammar check via LanguageTool#12831
ivandrofly wants to merge 1 commit into
SubtitleEdit:mainfrom
ivandrofly:grammar-check-languagetool

Conversation

@ivandrofly

@ivandrofly ivandrofly commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

A new Tools → Grammar check (LanguageTool)… window that checks the subtitle against a LanguageTool server - the public API or a self-hosted one (e.g. the docker image) - and applies the fixes the user ticks. It complements AI review: rule based, so it points at an exact span and offers concrete replacements instead of rewriting a line, it is much faster, and with a self-hosted server the text never leaves the machine.

  • src/libuilogic/Grammar/LanguageToolClient (/v2/check, /v2/languages, picky level, disabled rules, optional premium credentials), LanguageToolAnnotatedText (builds the annotated document and maps the answer back), LanguageToolFix (applies several fixes to one line). Kept out of the UI project so seconv can use it later.
  • src/ui/Features/Tools/GrammarCheck/ — the window and its view models. Server box with a test-connection button, language list served by the server (defaulting to the auto-detected subtitle language), picky toggle, category filter chips, a checkbox grid with before/after diffs, a replacement picker for the selected row, and a small settings dialog for user name / API key / disabled rules / lines per request.
  • Menu entry (both the normal and the native macOS menu), DI registration, Se.Settings.Tools.GrammarCheck, localizable strings, and a docs page.

Formatting tags, ASSA override blocks, music symbols and the line break inside a subtitle are sent as markup, so LanguageTool neither checks nor counts them as words, while the offsets it returns still point into the original line - a fix lands exactly where it belongs and the tags stay untouched. An issue spanning a tag or a line break is dropped rather than applied. Lines whose sentence continues into the next subtitle are joined with interpretAs, so a sentence is checked the way it reads on screen and agreement errors spread over two lines are found; fixes are still applied per line, so timing and reading speed are unaffected.

Nothing is applied automatically: spelling/grammar/punctuation/casing fixes start ticked, style suggestions start unticked, and rules that offer no replacement cannot be ticked at all.

Test plan

  • Tools → Grammar check (LanguageTool)… opens; the language drop-down fills and the status line reads "Connected - N languages available"
  • Point Server at an unreachable address and press the refresh button - the error is shown in the status line, the window stays usable
  • Check an English subtitle containing e.g. <i>He go to school</i> / I has a apple - issues appear per line with category tags and before/after diffs
  • Select a row with several replacements - the drop-down under the grid appears, picking another option updates the After column
  • Filter with the category chips; counts match the number of rows in each category
  • Untick some rows, press Apply N fixes - only the ticked fixes are applied, several fixes on one line all land correctly, and Ctrl+Z reverts the whole run in one step
  • A line wrapped in <i>…</i> or starting with {\an8} keeps its tags after applying a fix inside it
  • A sentence split over two subtitles gets its agreement error reported, and applying the fix does not move words between the lines
  • Press Stop mid-check - what was found so far stays in the grid
  • Settings… - user name/API key/disabled rules/lines per request survive a restart; a rule id in "disabled rules" makes that rule stop firing

UI

image

🤖 Generated with Claude Code

New Tools window that checks the subtitle against a LanguageTool server -
the public API or a self-hosted one - and applies the fixes you tick.

Formatting tags, ASSA override blocks, music symbols and the line break
inside a subtitle are sent as markup, so LanguageTool neither checks nor
counts them, while the offsets it answers with still point into the
original line - a fix lands exactly where it belongs and the tags stay
untouched. Issues spanning a tag or a line break are dropped rather than
applied. Lines whose sentence continues into the next subtitle are
checked as one sentence, so errors spread over two lines are found.

The client and the offset mapping live in libuilogic so the command line
converter can use them later; the window reuses the AI review category
vocabulary, colours and diff highlighting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ivandrofly

Copy link
Copy Markdown
Member Author

I also have https://languagetool.ivandrofly.org that any one can use or you can run your own https://github.com/Erikvl87/docker-languagetool

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.

1 participant