flutterdev.in › Packages › universal_spell_check

universal_spell_check

Spell check for Flutter TextFields on web, macOS, Windows and Linux too: native checkers on desktop, a pure-Dart Hunspell engine on the web.

v0.1.1160/160 pub pointsMITAndroidiOSmacOSWindowsLinuxWeb
universal_spell_check: ^0.1.1

Spell checking for Flutter TextFields on every platform.

Typing misspelled words in a Flutter web TextField: red underlines appear, right-click shows suggestions, clicking one fixes the word

Flutter web, with the bundled pure-Dart Hunspell engine: misspellings get underlined as you type, right-click offers suggestions, and picking one replaces the word.

Right-click suggestions in a Flutter web TextField

Flutter's built-in spell check (SpellCheckConfiguration + DefaultSpellCheckService) only works on Android and iOS. Web, macOS, Windows and Linux get nothing. This is flutter/flutter#40682. This package adds a SpellCheckService that works on all six platforms and plugs straight into the existing Flutter API.

Platform Engine Notes
Android Flutter DefaultSpellCheckService Uses the system spell checker service
iOS Flutter DefaultSpellCheckService Uses UITextChecker
macOS 10.15+ NSSpellChecker (Swift) Every language macOS has a dictionary for
Windows 8+ ISpellChecker (C++) Every language pack installed on Windows
Linux Enchant-2 (C), loaded with dlopen Needs libenchant-2-2 plus e.g. hunspell-en-us. Without them it reports unavailable and does not crash
Web Pure-Dart Hunspell engine Bundled en_US dictionary. Any other Hunspell dictionary can be loaded from assets or a URL

With the default SpellCheckBackend.auto, a desktop OS that cannot check a locale falls back to the Hunspell engine if a dictionary exists for it (en_US ships in the package).

Install

dependencies:
  universal_spell_check: ^0.1.1

Usage

import 'package:universal_spell_check/universal_spell_check.dart';

TextField(
  spellCheckConfiguration: UniversalSpellCheck.configuration(),
  // Right-click (desktop/web) or long-press menu with suggestions + "Ignore":
  contextMenuBuilder: UniversalSpellCheck.contextMenuBuilder,
)

On the web, call this once at startup so right-click opens Flutter's menu (with suggestions) and not the browser's:

await UniversalSpellCheck.useFlutterContextMenuOnWeb();

Using only the service

TextField(
  spellCheckConfiguration: SpellCheckConfiguration(
    spellCheckService: UniversalSpellCheckService.instance,
    misspelledTextStyle: UniversalSpellCheck.misspelledTextStyle,
  ),
)

Options

final service = UniversalSpellCheckService(
  backend: SpellCheckBackend.auto,      // auto | native | hunspell
  hunspellDictionaries: {
    'en': const HunspellSource.bundledEnUS(),
    'de': const HunspellSource.asset('assets/de_DE.aff', 'assets/de_DE.dic'),
    'fr': HunspellSource.url(Uri.parse('https://example.com/fr.aff'),
                             Uri.parse('https://example.com/fr.dic')),
  },
  maxSuggestions: 5,
  useIsolate: true,                     // Hunspell off the UI isolate (native)
  ignoredWords: ['Flutter'],
);

await service.availability(const Locale('de', 'DE')); // which engine, which dictionary
await service.warmUp(const Locale('en', 'US'));        // parse the dictionary early
service.ignoreWord('Manish');

Create a service once, for example in a State or as a global. Do not create one inside build().

The Hunspell engine on its own

final dict = HunspellDictionary.parse(affText, dicText);
final hunspell = Hunspell(dict);
hunspell.check('colour');          // false with en_US
hunspell.suggest('recieve');       // [receive, relieve]

final checker = HunspellSpellChecker(const HunspellSource.bundledEnUS());
await checker.check('I recieve teh mail'); // List<SpellCheckRange>

Supported .aff features: SET, FLAG (char/long/num/UTF-8), AF, PFX/SFX (conditions, strip, cross product, continuation classes), TRY, KEY, REP, MAP, ICONV/OCONV, KEEPCASE, NOSUGGEST, FORBIDDENWORD, NEEDAFFIX, ONLYINCOMPOUND, COMPOUNDRULE, COMPOUNDMIN, WORDCHARS, BREAK.

Limitations

Dictionary license

dictionaries/en_US.* comes from SCOWL (wordlist.aspell.net, 2020.12.07, size 60) and uses its own permissive license, in dictionaries/LICENSE-en_US.txt. The package code is MIT.

More Flutter packages