SpellChecker

A small Elixir library for checking spelling in English, Spanish and French against bundled dictionaries, with suggestions, autocorrect, custom dictionaries, and whole-text checking.

Installation

The package can be installed by adding spell_checker to your list of dependencies in mix.exs:

def deps do
  [
    {:spell_checker, "~> 0.3.0"}
  ]
end

Documentation can be found at https://hexdocs.pm/spell_checker.

Usage

SpellChecker.is_correct("hello")
# {:ok, true}

SpellChecker.is_correct?(["hello", "worlld", "Programming"])
# ["Programming", "hello"]

SpellChecker.is_correct!("worlld")
# ["world", "worldly", "worlds", "wold", "word"]

SpellChecker.correct("Helo")
# {:corrected, "Hello"}

SpellChecker.check_text("hello wrold")
# [{"wrold", ["wold", "world", "worlds", "would", "word"]}]

# Extend the dictionary with your own words (kept for the life of the node)
SpellChecker.add_words(["hexdocs", "genserver"])
SpellChecker.is_correct("GenServer")
# {:ok, true}

SpellChecker.clear_custom_words()

# Or swap a bundled dictionary out entirely, or add a new language
SpellChecker.load_dictionary!(["ẹ", "kú", "àárọ̀"], lang: :yo)

Languages

English (:en), Spanish (:es) and French (:fr) are bundled. Every function takes a lang: option, defaulting to :en:

SpellChecker.is_correct("canción", lang: :es)
# {:ok, true}

SpellChecker.correct("Corazon", lang: :es)
# {:corrected, "Corazón"}

SpellChecker.check_text("Je suis allé à l’ecole", lang: :fr)
# [{"l’ecole", ["l'école", "l'écoles", "l'écoule", "l'écoulé", "l'éole"]}]

SpellChecker.languages()
# [:en, :es, :fr]

To change the default language for your whole app:

# config/config.exs
config :spell_checker, default_lang: :fr

Missing or wrong accents ("ecole", "nino") are treated as the closest possible mistake, so the accented word is suggested first. French elisions like l'école and qu'aujourd'hui are checked as two words, and typographic apostrophes (’) work the same as '.

Each language's dictionary is read from disk the first time it's used and cached in memory (via :persistent_term) for the life of the running node, so repeated lookups are cheap. Loading takes about 2 seconds and ~70 MB for Spanish, ~50 MB for French, and ~4 MB for English; only the languages you use are loaded. Custom words added with add_words/2 are per language (add_words(words, lang: :es)).

Suggestions only consider words that start with the same letter (ignoring accents), which keeps them fast for the large Spanish and French dictionaries.

The Spanish and French word lists come from the LibreOffice Hunspell dictionaries and keep their upstream licenses (MPL); see priv/dictionaries/README.md.