PHPackages                             kit-jotform/php-ftfy - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. kit-jotform/php-ftfy

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

kit-jotform/php-ftfy
====================

Fixes text for you — PHP port of the Python ftfy library

v1.3.1(1mo ago)111↓90%MITPHPPHP &gt;=8.1

Since Mar 26Pushed 1mo agoCompare

[ Source](https://github.com/kit-jotform/php-ftfy)[ Packagist](https://packagist.org/packages/kit-jotform/php-ftfy)[ Docs](https://github.com/kit-jotform/php-ftfy)[ RSS](/packages/kit-jotform-php-ftfy/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (3)Versions (9)Used By (0)

php-ftfy: fixes text for you
============================

[](#php-ftfy-fixes-text-for-you)

A PHP 8.1+ text-fixing library based on the [Python ftfy library](https://github.com/rspeer/python-ftfy) (version 6.3.1) by Robyn Speer.

```
use Ftfy\Ftfy;

echo Ftfy::fixText("(à¸‡'âŒ£')à¸‡");
// (ง'⌣')ง
```

What it does
------------

[](#what-it-does)

ftfy fixes mojibake — text that was encoded in UTF-8 but decoded as something else (Windows-1252, Latin-1, etc.), producing garbled characters.

```
use Ftfy\Ftfy;

// Fix common mojibake
Ftfy::fixText('âœ" No problems');
// ✔ No problems

// Fix multiple layers of mojibake
Ftfy::fixText('The Mona Lisa doesnÃƒÂ¢Ã¢â€šÂ¬Ã¢â€žÂ¢t have eyebrows.');
// "The Mona Lisa doesn't have eyebrows."

// Fix HTML entities outside of HTML
Ftfy::fixText('P&EACUTE;REZ');
// PÉREZ

// Correctly-decoded text is left unchanged
Ftfy::fixText('IL Y MARQUÉ…');
// IL Y MARQUÉ…
```

Installing
----------

[](#installing)

```
composer require kit-jotform/php-ftfy
```

**Requirements:** PHP &gt;= 8.1, `ext-mbstring`, `ext-intl`

Usage
-----

[](#usage)

### `Ftfy::fixText(string $text, ?TextFixerConfig $config = null): string`

[](#ftfyfixtextstring-text-textfixerconfig-config--null-string)

Fix all encoding issues in a string.

```
use Ftfy\Ftfy;

$fixed = Ftfy::fixText('Ã\xa0 perturber la rÃ©flexion');
// à perturber la réflexion
```

### `Ftfy::fixEncoding(string $text): string`

[](#ftfyfixencodingstring-text-string)

Fix only encoding/mojibake issues, without applying other text fixes.

```
$fixed = Ftfy::fixEncoding("l'humanitÃ©");
// l'humanité
```

### `Ftfy::needsFix(string $text, ?TextFixerConfig $config = null): bool`

[](#ftfyneedsfixstring-text-textfixerconfig-config--null-bool)

Fast dry-run that checks whether text needs fixing without performing corrections. Use as a gate before `fixText()` on hot paths — 10-26x faster depending on input.

```
use Ftfy\Ftfy;

if (Ftfy::needsFix($text)) {
    $text = Ftfy::fixText($text);
}

// Clean text exits almost instantly
Ftfy::needsFix('Hello world');   // false
Ftfy::needsFix('Héllo wörld');   // false

// Detects all fixable issues
Ftfy::needsFix('schÃ¶n');        // true (mojibake)
Ftfy::needsFix('&amp; test');    // true (HTML entity)
Ftfy::needsFix("\u{201C}test");  // true (curly quotes)
```

Respects `TextFixerConfig` — disabled fixers are skipped:

```
$config = new TextFixerConfig(uncurlQuotes: false);
Ftfy::needsFix("\u{201C}test", $config); // false
```

### `Ftfy::fixAndExplain(string $text, ?TextFixerConfig $config = null): array`

[](#ftfyfixandexplainstring-text-textfixerconfig-config--null-array)

Returns `['text' => string, 'explanation' => array]` with the fixed text and a list of changes made.

```
[$fixed, $explanation] = array_values(Ftfy::fixAndExplain('âœ" No problems'));
// $fixed      => '✔ No problems'
// $explanation => [['name' => 'fix_encoding', 'cost' => 1, ...]]
```

### Configuration

[](#configuration)

```
use Ftfy\Ftfy;
use Ftfy\TextFixerConfig;

$config = new TextFixerConfig(
    unescapeHtml: 'auto',           // 'auto', true, or false — decode HTML entities
    removeTerminalEscapes: true,    // strip ANSI terminal escape sequences
    fixEncoding: true,              // fix mojibake
    restoreByteA0: true,            // restore byte 0xA0 as non-breaking space
    replaceLossySequences: true,    // replace lossy codec sequences
    decodeInconsistentUtf8: true,   // decode inconsistent UTF-8
    fixC1Controls: true,            // fix C1 control characters
    fixLatinLigatures: true,        // expand Latin ligatures (ﬁ → fi)
    fixCharacterWidth: true,        // normalize fullwidth characters
    uncurlQuotes: true,             // straighten curly quotes (' " → ' ")
    fixLineBreaks: true,            // normalize line breaks to \n
    fixSurrogates: true,            // fix surrogate characters
    removeControlChars: true,       // remove control characters
    normalization: 'NFC',           // Unicode normalization form (NFC, NFD, NFKC, NFKD, or null)
);

$fixed = Ftfy::fixText($garbled, $config);
```

Use `$config->with(uncurlQuotes: false)` to produce a modified copy.

> **Note on large inputs:** Internally, regex matching uses chunked processing for inputs larger than 8 KB to avoid hitting PCRE backtracking/recursion limits. No configuration is needed — this is handled automatically.

Command-line usage
------------------

[](#command-line-usage)

A CLI script is included at `bin/ftfy`.

**Fix a string directly:**

```
php bin/ftfy "schÃ¶n"
# schön
```

**Pipe from stdin:**

```
echo "Hello &amp; world" | php bin/ftfy
# Hello & world
```

**Fix a file:**

```
php bin/ftfy --file input.txt
```

**Show what was fixed** (explanation goes to stderr):

```
php bin/ftfy --explain "schÃ¶n"
# schön
#
# explanation:
#   - encode: sloppy-windows-1252
#   - decode: utf-8
```

**Check if text needs fixing** (exit code 1 = needs fix):

```
php bin/ftfy --needs-fix "schÃ¶n"
# true

php bin/ftfy --needs-fix "schön"
# false
```

**Override config options** with `-c key=value` (repeatable):

```
php bin/ftfy -c uncurlQuotes=false "It\u2019s great"
php bin/ftfy -c normalization=NFKC -c fixLineBreaks=false --file input.txt
```

**Fix mojibake inside a JSON file** with `-j` (minimal-diff: only changes string values that contain mojibake; preserves whitespace, key order, and untouched escapes):

```
php bin/ftfy -j --file broken.json > fixed.json
```

When mojibake lives inside JSON string values, the raw file contains only ASCII escape sequences like `â€”`, so plain `php bin/ftfy --needs-fix broken.json` reports `false` — the mojibake bytes only appear *after* JSON decoding. `-j` walks the JSON byte-by-byte (no regex, no PCRE recursion limits), decodes each string literal individually, and rewrites only those that `needsFix` flags. Other strings and all structural bytes pass through verbatim.

`-j` composes with `-n` and `-e`:

```
php bin/ftfy -j -n --file broken.json     # short-circuits at first bad string
php bin/ftfy -j -e --file broken.json     # fix + de-duplicated explain plan on stderr
```

**Install globally** (optional):

```
ln -s "$(pwd)/bin/ftfy" /usr/local/bin/ftfy
ftfy "schÃ¶n"
```

**Options:**

OptionShortDescription`--explain``-e`Print what was fixed (to stderr)`--needs-fix``-n`Print true/false; exit 0 if no fix needed, 1 if fix needed`--json``-j`Fix mojibake inside JSON string values (minimal-diff output; composes with `-n` and `-e`)`--file``-f`Read input from a file`--config key=val``-c`Set a `TextFixerConfig` option (repeatable)`--help``-h`Show helpBoolean config keys accept `true`/`false`/`1`/`0`: `uncurlQuotes`, `fixEncoding`, `fixLineBreaks`, `fixSurrogates`, `removeControlChars`, `removeTerminalEscapes`, `restoreByteA0`, `replaceLossySequences`, `decodeInconsistentUtf8`, `fixC1Controls`, `fixLatinLigatures`, `fixCharacterWidth`. String keys: `unescapeHtml` (`auto`/`true`/`false`), `normalization` (`NFC`/`NFKC`/`null`), `maxDecodeLength` (integer).

Running tests
-------------

[](#running-tests)

```
composer install
vendor/bin/phpunit tests/
```

Credits
-------

[](#credits)

- Original Python library: [ftfy](https://github.com/rspeer/python-ftfy) by [Robyn Speer](https://github.com/rspeer), licensed under Apache 2.0
- PHP port licensed under MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance93

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

8

Last Release

37d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5406a8fe3808787f7b31bfc2159f780ddfcc3f8b08a5763eb7332eead5d12518?d=identicon)[kit-jotform](/maintainers/kit-jotform)

---

Top Contributors

[![kit-jotform](https://avatars.githubusercontent.com/u/245003038?v=4)](https://github.com/kit-jotform "kit-jotform (25 commits)")

---

Tags

unicodeencodingtextfixftfymojibake

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/kit-jotform-php-ftfy/health.svg)

```
[![Health](https://phpackages.com/badges/kit-jotform-php-ftfy/health.svg)](https://phpackages.com/packages/kit-jotform-php-ftfy)
```

###  Alternatives

[nette/utils

🛠 Nette Utils: lightweight utilities for string &amp; array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.

2.1k417.9M1.7k](/packages/nette-utils)[paragonie/constant_time_encoding

Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)

903351.6M180](/packages/paragonie-constant-time-encoding)[voku/portable-utf8

Portable UTF-8 library - performance optimized (unicode) string functions for php.

51923.1M48](/packages/voku-portable-utf8)[jbroadway/urlify

A fast PHP slug generator and transliteration library that converts non-ascii characters for use in URLs.

6757.8M76](/packages/jbroadway-urlify)[ausi/slug-generator

Slug Generator

8002.3M24](/packages/ausi-slug-generator)[ckeditor/ckeditor

JavaScript WYSIWYG web text editor.

5244.3M79](/packages/ckeditor-ckeditor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
