PHP Multi Byte str_replace?

Я пытаюсь сделать акцентированную замену символов на PHP, но получаю фанковые результаты, полагаю, потому, что я использую строку UTF-8, а str_replace не может правильно обрабатывать многобайтовые строки.

$accents_search = array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ'); $accents_replace = array('a','a','a','a','a','a','a','A','A','A','A','A','e','e', 'e','e','E','E','E','E','i','i','i','i','I','I','I','I','oe','o','o','o','o','o','o', 'O','O','O','O','O','u','u','u','U','U','U','c','C','N','n'); $str = str_replace($accents_search, $accents_replace, $str); 

Результаты:

 Ørjan Nilsen ->  orjan Nilsen 

Ожидаемый результат:

 Ørjan Nilsen -> Orjan Nilsen 

Изменить: у меня есть обработчик внутренних символов, установленный в UTF-8 (в соответствии с mb_internal_encoding ()), также значение $ str является UTF-8, поэтому из того, что я могу сказать, все используемые строки – UTF-8. Устанавливает ли str_replace () набор символов и правильно их использует?

Похоже, что строка не была заменена, потому что ваша входная кодировка и несоответствие кодировки файла.

Согласно документации php функция str_replace является двоичной, что означает, что она может обрабатывать кодированный текст UTF-8 без потери данных.

Можно удалить диакритические знаки, используя форму нормализации Unicode формы D (NFD) и Unicode.

NFD преобразует что-то вроде «ü» умлаут из «ЛАТИНСКОГО МАЛЕНЬКОГО ПИСЬМА U С ДИАЕРЕЗОМ» (это письмо) в «ЛАТИНСКОЕ МАЛОЕ ПИСЬМО U» (буква) и «КОМБИНИРОВАННАЯ ДИАВЕРСИЯ» (а не буква).

 header('Content-Type: text/plain; charset=utf-8'); $test = implode('', array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ')); $test = Normalizer::normalize($test, Normalizer::FORM_D); // Remove everything that's not a "letter" or a space (eg diacritics) // (see http://de2.php.net/manual/en/regexp.reference.unicode.php) $pattern = '/[^\pL ]/u'; echo preg_replace($pattern, '', $test); 

Вывод:

 aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn 

Класс Normalizer является частью пакета PECL intl . (Сам алгоритм не очень сложный, но нужно загружать много символов afaik. Я написал PHP-реализацию некоторое время назад.)

(Я добавляю эти два месяца, потому что думаю, что это хорошая техника, которая не известна достаточно широко.)

Попробуйте определить эту функцию:

 if (!function_exists('mb_str_replace')) { function mb_str_replace($search, $replace, $subject) { if (is_array($subject)) { foreach ($subject as $key => $val) { $subject[$key] = mb_str_replace((string)$search, $replace, $subject[$key]); } return $subject; } $pattern = '/(?:'.implode('|', array_map(create_function('$match', 'return preg_quote($match[0], "/");'), (array)$search)).')/u'; if (is_array($search)) { if (is_array($replace)) { $len = min(count($search), count($replace)); $table = array_combine(array_slice($search, 0, $len), array_slice($replace, 0, $len)); $f = create_function('$match', '$table = '.var_export($table, true).'; return array_key_exists($match[0], $table) ? $table[$match[0]] : $match[0];'); $subject = preg_replace_callback($pattern, $f, $subject); return $subject; } } $subject = preg_replace($pattern, (string)$replace, $subject); return $subject; } }