giovani/spelling

PHP spell checking library with Composite Pattern — Brazilian Portuguese (pt_BR) and American English (en_US) rules, Enchant dictionary support, and custom word lists.

Maintainers

Statistics

Installs: 296

Dependents: 0

Suggesters: 0

Stars: 0

v2.0.0 2026-06-23 23:01 UTC

This package is auto-updated.

Last update: 2026-08-10 17:28:19 UTC


README

PHP spell checking library with Composite Pattern — Brazilian Portuguese (pt_BR) and American English (en_US).

PHP Version License: MIT Latest Stable Version Total Downloads

Features

  • Brazilian Portuguese rules — 2009 Spelling Reform: trema removal, open diphthong accents, hyphenation
  • American English rules — US vs UK spelling, pronoun I capitalization, days/months enforcement
  • System dictionary support — via PHP ext-enchant (Hunspell, Aspell), any language
  • Custom word lists — allowlist domain-specific vocabulary at runtime
  • Composite Pattern — chain multiple checkers transparently with unanimous AND logic
  • Spell suggestions — every checker surfaces correction candidates via getSuggestions()

Requirements

Dependency Version Notes
PHP ^8.1 Required
doctrine/inflector ^2.0 Required
ext-enchant any Optional — only needed for EnchantChecker

Installation

composer require giovani/spelling

Optional: system dictionaries for EnchantChecker

# Ubuntu / Debian
sudo apt-get install aspell-pt-br hunspell-pt-br

# macOS
brew install enchant

Verify the extension is loaded:

php -m | grep enchant

Quick Start

Brazilian Portuguese (recommended)

use Giovani\Spelling\SpellingFactory;

$checker = SpellingFactory::createDefault();

// Post-reform words are accepted
$checker->isValid('ideia');    // true
$checker->isValid('linguiça'); // true

// Pre-reform forms are rejected and corrected
$checker->isValid('idéia');    // false
$checker->getSuggestions('idéia');    // ['ideia']
$checker->getSuggestions('lingüiça'); // ['linguiça']

// Months and days of the week must be lowercase in pt_BR
$checker->isValid('janeiro');  // true
$checker->isValid('Janeiro');  // false
$checker->getSuggestions('Janeiro'); // ['janeiro']

With a custom vocabulary

Pass additional words that should always be accepted (brand names, technical terms, etc.):

$checker = SpellingFactory::createDefault(['MinhaMarca', 'Laravel', 'NomeTécnico']);

$checker->isValid('minhamarca'); // true
$checker->isValid('laravel');    // true

American English

use Giovani\Spelling\Checkers\CompositeSpellingChecker;
use Giovani\Spelling\Checkers\AmericanEnglishRulesChecker;
use Giovani\Spelling\Checkers\EnchantChecker;

$composite = new CompositeSpellingChecker();
$composite->addChecker(new AmericanEnglishRulesChecker());
$composite->addChecker(new EnchantChecker('en_US'));

$composite->isValid('color');   // true
$composite->isValid('colour');  // false — British spelling rejected
$composite->getSuggestions('colour'); // ['color']

$composite->isValid('I');       // true
$composite->isValid('i');       // false — pronoun must be capitalized
$composite->getSuggestions('i'); // ['I']

$composite->isValid('Monday');  // true
$composite->isValid('monday');  // false

Building fully custom composites

use Giovani\Spelling\Checkers\CompositeSpellingChecker;
use Giovani\Spelling\Checkers\PortugueseRulesChecker;
use Giovani\Spelling\Checkers\SimpleSpellingChecker;

$composite = new CompositeSpellingChecker();
$composite->addChecker(new PortugueseRulesChecker());
$composite->addChecker(new SimpleSpellingChecker(['PHP', 'Composer', 'Packagist']));

$composite->isValid('php');    // true
$composite->isValid('idéia');  // false — Portuguese rule violation

Available Checkers

Checker Description Language
SimpleSpellingChecker Validates against a custom in-memory allowlist Any
CompositeSpellingChecker Chains multiple checkers (unanimous AND logic) Any
EnchantChecker System dictionary via ext-enchant Any (pt_BR, en_US, …)
PortugueseRulesChecker 2009 Spelling Reform rules for pt_BR Portuguese
AmericanEnglishRulesChecker US spelling and capitalization conventions English (US)
InflectorChecker Word normalization via Doctrine Inflector English

All checkers implement the same interface:

interface SpellingCheckerInterface
{
    public function isValid(string $word): bool;

    /** @return string[] */
    public function getSuggestions(string $word): array;
}

Architecture

The library is built on the Composite design pattern. CompositeSpellingChecker holds a collection of SpellingCheckerInterface leaves and requires unanimous approval — all checkers must return true for a word to be considered valid. Suggestions are aggregated from every checker and deduplicated.

SpellingCheckerInterface
├── CompositeSpellingChecker   ← groups checkers, AND logic, deduplicates suggestions
│   ├── PortugueseRulesChecker
│   ├── InflectorChecker
│   ├── EnchantChecker
│   └── SimpleSpellingChecker
└── (any custom checker implementing the interface)

SpellingFactory::createDefault() assembles the recommended pt_BR stack automatically, with EnchantChecker added gracefully when ext-enchant is available.

Running Tests

composer install
vendor/bin/phpunit

Documentation

Full documentation is available in the docs/ directory:

Contributing

Contributions, bug reports, and feature requests are welcome. Please open an issue or pull request on GitHub.

License

MIT — see LICENSE.