Сконвертировать строку в utf8

Имеется строка в массиве со значением Алмасу буферіне көшіру. Есть алгоритм, который конвертирует все строки из кодировки 1251 в UTF8.

function json_fix_cyr($var) {
    if (is_array($var)) {
        $new = array();
        foreach ($var as $k => $v) {
            $new[json_fix_cyr($k)] = json_fix_cyr($v);
        }
        $var = $new;
    } elseif (is_object($var)) {
        $vars = get_object_vars($var);
        foreach ($vars as $m => $v) {
            $var->$m = json_fix_cyr($v);
        }
    } elseif (is_string($var)) {
        $var = iconv('cp1251', 'utf-8', $var); // здесь происходит конвертация
    }
    return $var; 
}

Требуется для данной строки сделать исключение, но пока не понимаю, как отловить определённый utf8 символ в строке. Если делаю так:

    $new = '';
    for ($b = 0; $b < strlen($var); $b++)
        if ($var[$b] === 'ө')
            $new .= 'ө';
        else
            $new .= iconv('cp1251', 'utf-8', $var[$b]);
    $var = $new;

то символ ө конвертируется в вопросительный знак. Если конвертацию не делать, в других местах возникают ошибки. Однако, если просто добавить данный символ к конвертированной строке, то далее он отображается без ошибок. Как отловить нужные мне символы?


Ответы (2 шт):

Автор решения: Егор Банин

Существует несколько вариантов cp1251. Буква ө присутствует в казахском и татарском вариантах. Функция iconv ничего об этом не знает. То есть в таблице соответствия символов cp1251 символам utf-8 нет буквы ө.

В вашем случае речь о казахской кодировке. Вы можете посмотреть (на машине, где будет работать ваш скрипт) какие кодировки поддерживает iconv, набрав в консоли iconv -l. Если там найдётся KZ-1048, то можно конвертировать так: iconv('KZ-1048', 'UTF-8', $var). Если кодировка KZ-1048 отсутствует, то её, скорее всего, можно как-то установить. Я не знаю как это делается, гуглите.

Костыльное решение (на разок, чтобы перевести всё в utf и забыть про муки с разными языками ваших пользователей) заключается в том, чтобы сделать замену одного неудобного символа (на самом деле их там больше) вручную.

Вы двигались в правильном направлении, но, скорее всего, не учли, что текст в вашем скрипте тоже в какой-то кодировке. Современные редакторы кода обычно по умолчанию сохраняют ваш код в utf-8. То есть строка 'ө' в вашем коде это utf-8 символ.

В казахской кодировке ө стоит на месте ґ в стандартном cp1251 (кстати, что у вас получалось при простой конвертации iconv('cp1251', 'utf-8', $var)?). То есть ord('ө') === 180.

<?php // файл в KZ-1048

$text = 'Алмасу буферіне көшіру';

$result = '';
for ($i = 0; $i < strlen($text); ++$i) {
    if (ord($text[$i]) === 180) {
        $result .= mb_chr(1257, 'UTF-8'); // ө в utf-8
    } else {
        $result .= iconv('cp1251', 'utf-8', $text[$i]);
    }
}

header('Content-Type: text/html; charset=utf-8');
echo $result;

Не забывайте про заглавную Ө и может быть какие-нибудь ещё символы, которые отличаются от cp1251.

→ Ссылка
Автор решения: Ипатьев

Чтобы сконвертировать строку в utf-8, надо знать исходную кодировку этой строки. И дальше воспользоваться одной из функций перекодирования, доступных в РНР. Например

// из Windows-1251 в UTF-8
$string = iconv('cp1251', 'utf-8', $string);

или

// из UTF-16 в UTF-8
$string = mb_convert_encoding($string, 'utf-8', 'utf-16');
→ Ссылка