Installation:
composer require amalricbzh/typo-fixer-bundle
Add to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):
return [
// ...
AmalricBzh\TypoFixerBundle\TypoFixerBundle::class => ['all' => true],
];
First Use Case:
Inject the TypoFixer service into a controller or command:
use AmalricBzh\TypoFixerBundle\Service\TypoFixer;
class MyController extends Controller {
public function __construct(private TypoFixer $typoFixer) {}
public function fixTypo(Request $request) {
$text = $request->input('text');
$fixedText = $this->typoFixer->fix($text);
return response()->json(['fixed' => $fixedText]);
}
}
Test with a known typo:
curl -X POST http://your-app.test/api/fix-typo -d "text=Je vouldrais un café"
Expected output: Je voudrais un café.
Real-Time Form Validation: Use middleware to auto-correct typos in submitted forms:
namespace App\Http\Middleware;
use AmalricBzh\TypoFixerBundle\Service\TypoFixer;
class FixFrenchTypoMiddleware {
public function __construct(private TypoFixer $typoFixer) {}
public function handle($request, Closure $next) {
$data = $request->all();
foreach ($data as &$value) {
if (is_string($value)) {
$value = $this->typoFixer->fix($value);
}
}
return $next($request->merge($data));
}
}
Register in app/Http/Kernel.php:
protected $middleware = [
// ...
\App\Http\Middleware\FixFrenchTypoMiddleware::class,
];
Batch Processing: Process large datasets (e.g., database records) with a job:
use AmalricBzh\TypoFixerBundle\Service\TypoFixer;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class FixTypoJob implements ShouldQueue {
use Queueable;
public function __construct(
private TypoFixer $typoFixer,
private string $table,
private string $column
) {}
public function handle() {
DB::table($this->table)
->whereRaw("{$this->column} REGEXP '[a-zA-Z]')
->chunk(100, function ($records) {
foreach ($records as $record) {
$fixedValue = $this->typoFixer->fix($record->{$this->column});
$record->update([$this->column => $fixedValue]);
}
});
}
}
API Response Filtering: Auto-correct typos in API responses using a response filter:
namespace App\Filters;
use AmalricBzh\TypoFixerBundle\Service\TypoFixer;
class FrenchTypoFilter {
public function __construct(private TypoFixer $typoFixer) {}
public function apply($response) {
if ($response->isJson()) {
$data = $response->getData();
$this->fixNestedArray($data);
$response->setData($data);
}
return $response;
}
private function fixNestedArray(&$array) {
foreach ($array as &$value) {
if (is_array($value)) {
$this->fixNestedArray($value);
} elseif (is_string($value)) {
$value = $this->typoFixer->fix($value);
}
}
}
}
$fixedText = app('locale') === 'fr' ? $typoFixer->fix($text) : $text;
$cacheKey = 'typo_fixer:' . md5($text);
$fixedText = Cache::remember($cacheKey, now()->addHours(1), function() use ($text, $typoFixer) {
return $typoFixer->fix($text);
});
config/typo_fixer.php:
return [
'rules' => [
'vouldrais' => 'voudrais',
'café' => 'café', // Override if needed
],
];
False Positives:
$typoFixer->fix($text, ['exclude' => ['name', 'brand']]);
Performance:
Case Sensitivity:
$typoFixer->addRule('Vouldrais', 'Voudrais');
Non-French Text:
if (preg_match('/[àâäéèêëîïôöùûüçœæ]/', $text)) {
return $typoFixer->fix($text);
}
return $text;
$typoFixer->setLogger(app(\Psr\Log\LoggerInterface::class));
dd($typoFixer->getRules());
"Je Vouldrais"."Café, s'il vous plaît"."123 vouldrais 😊".Custom Rules: Extend the rule set dynamically:
$typoFixer->addRule('custom_typo', 'correction');
Or via a service provider:
public function register() {
$this->app->booted(function() {
$typoFixer = $this->app->make(TypoFixer::class);
$typoFixer->addRule('laravel', 'Laravel');
});
}
Event Listeners: Trigger actions on typo fixes (e.g., analytics):
$typoFixer->onFix(function(string $original, string $fixed) {
\Log::info("Typo fixed: '$original' → '$fixed'");
});
Language Support: While primarily French-focused, you can adapt it for other languages by:
TypoFixer class.$typoFixer->setRules(['spanish' => 'rules' => [...]]);
max_iterations config if dealing with nested typos (e.g., "vouldrais" → "voudrrais" → "voudrais").How can I help you explore Laravel packages today?