The Levenshtein distance counts how many edits it takes to turn one string into another. PHP's levenshtein() works on bytes, which gives wrong answers for many non-English characters. This RFC from Yuya Hamada adds grapheme_levenshtein() to the intl extension. It counts edits by grapheme cluster, meaning what a person sees on screen as a single character.

Why it helps

Some characters can be written more than one way. An "é" can be a single code point, or an "e" followed by a combining accent mark, and both look identical. The author first worked on mb_levenshtein(), but people on the internals list argued that counting by grapheme cluster made more sense, and the author agreed.

Here is the RFC's example with the two forms of "é":

var_dump(grapheme_levenshtein("\u{0065}\u{0301}", "\u{00e9}"));
// 0

The RFC notes that mb_levenshtein() doesn't handle this correctly. It shows a similar case with a Chinese character followed by a variation selector, an invisible code point that picks a glyph style. grapheme_levenshtein() returns 0 there too, while mb_levenshtein() returns 1.

The function

function grapheme_levenshtein(
    string $string1,
    string $string2,
    int $insertion_cost = 1,
    int $replacement_cost = 1,
    int $deletion_cost = 1
): int|false {}

Both strings must be valid UTF-8, and if either one isn't, the function returns false. Like levenshtein(), it lets you set a separate cost for insertions, replacements and deletions.

What it means for existing code

It only adds a function. The one risk is a clash if your own code already defines a function named grapheme_levenshtein().

The vote

It passed unanimously, 12 to 0, clearing the two-thirds majority it needed. Voting closed on April 16, 2025. The page lists PHP 8.5 as the target version and marks the RFC as implemented.