Сразу оговорюсь, что данный пост не претендует на статус официального документа, это должно быть хорошее подспорье по проблеме.
[spoiler]
Подготовка
- Для работы сайта на битрикс в utf8 абсолютно необходимо наличие модуля mbstring в php (это есть почти на любом хостинге) и установка параметра
mbstring.func_overload 2
С этим может быть проблема т.к. с версии php 5.2.8 параметр меняется глобально на весь сервер (). Уточните вопрос у хостера, но будьте осторожны если вам предложат CGI (см. ).
На VPS/выделенном сервере параметр без проблем меняется в php.ini. - Обязательно сделайте резервную копию работающего сайта, а лучше именно на копии проводите эксперименты. Если что-то пойдёт не так - вы можете потерять данные!
Этапы перехода
- Подготовить сервер как показано выше
- Добавить в /bitrix/php_interface/dbconn.php
define("BX_UTF", true); - Установить в /bitrix/.settings.php
utf_mode => array('value' => true, 'readonly' => true) - Изменить в настройках сайта кодировку с windows-1251 на utf-8
- Изменить в настройках языка ru кодировку с windows-1251 на utf-8
- Конвертировать все файлы в utf8
- Конвертировать БД в utf8
- Сменить в /bitrix/php_interface/after_connect.php на
$DB->Query("SET NAMES 'cp1251'";); и в файле /bitrix/php_interface/after_connect_d7.php$DB->Query("SET NAMES 'utf8'";); $connection->queryExecute("SET NAMES 'utf8'");
$connection->queryExecute('SET collation_connection = "utf8_unicode_ci"'); - Сбросить весь кеш
- Выйти и зайти на сайт чтобы обновить данные сессии
Практическая сторона вопроса
После смены кодировки сайта публичная часть принимает вид:
Это нормально, браузер пытается показать данные не в той кодировке. Теперь после всех действий внешний вид восстановится, и мы увидим, что процесс прошёл успешно.
Большое число файлов надо конвертировать по шагам, для этого буду использовать . По большому счёту, тут надо только переделать функцию замены в конвертацию через mb_convert_encoding.
Примечание. Часто при использовании внешних программ для конвертации в файлы добавляется специальная последовательность символов, т.н. . Эти символы должны находиться только вначале файла, а поскольку итоговая html страница является составной из нескольких php файлов, то спецсимволы появляются в теле html страницы. Если делаете вручную - не сохраняйте с BOM!
Для конвертации базы надо сменить кодировку базы, всех таблиц и всех текстовых полей таблиц. Вручную это тоже делать не очень удобно. Решил сделать конвертацию файлов и базы в одном скрипте.
Скрипт выполняет операции:
| - Конвертировать все файлы в utf8 - Конвертировать БД в utf8 |
Остальное следует делать вручную по списку в том порядке, как написано.
Можно скачать по ссылке:
В итоге получил картинку
Теперь, словно, девушка даже слегка улыбнулась

Обновление от 20.02.2012
- Теперь конвертируются все файлы, не только языки. При этом делается авто определение кодировки файла, а значит можно выполнять конвертацию повторно.
- Для кодировки базы указывается сравнение utf8_unicode_ci (требуется продуктом).
- Исправлены ошибки конвертации базы.
- Шаг конвертации файлов можно пропустить.
Дополнение от 10.09.2018
Если вы использовали интеграцию с почтой, проверьте настройки ящиков, если там установлена кодировка, переключите кодировку сайта.
Спасибо! Большое, человеческое спасибо! Впредь буду сразу в utf8 ставить систему
Как с этим можно разобраться?
1.Принял соглашение в личном кабинете marketplace - обновление платформы.
2.Далее добавил в /bitrix/php_interface/dbconn.php
define("BX_UTF", true);4.Далее выполнил скрипт приложенный выше, только выполнял не все действия, выполнил проверку и перекодировал данные сайта. БД не трогал.
5.В новой вкладке зашел в админку для выполнения SQL запроса и выполнил следующее:
SEL ECT CONCAT('ALT ER TABLE `', t.`TABLE_SCHEMA`, '`.`', t.`TABLE_NAME`, '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') as sqlcode FR OM `information_schema`.`TABLES` t WHERE 1 AND t.`TABLE_SCHEMA` = 'db_name' ORDER BY 1Данный запрос выведет строки. Эти строки раскроем, чтобы были на одну страницу, выделим и выполним их как sql запрос.
Пример:
6.Сменил в /bitrix/php_interface/after_connect.php
$DB->Query("SET NAMES 'cp1251'");$DB->Query("SET NAMES 'utf8'");8.Вышел и зашел на сайт, чтобы обновить данные сессии.
Надеюсь, кому-нибудь это пригодится.
Версия 15.5, конвертировались из cp1251 без проблем.
P.S. слетели гаджеты раб стола. Вроде все)
По времени - 40 минут, делал первый раз)))
Я правильно понимаю, что в пунктах:
10. Установить в /bitrix/php_interface/after_connect.php по sftp:
$DB->Query('SET collation_connection = "utf8_unicode_ci"');
$connection->queryExecute('SET collation_connection = "utf8_unicode_ci"');
Добавлю от себя:
В настройках Сайта -> Региональные настройки, надо ставить кодировку в правильном написании utf-8 (через дефис), в противном случаи некоторые ваши клиенты (да и сервисы) будут ловить "кракозябыры" - например те кто работает из под internet explorer 9 (IE9 и ниже)
Все сериализованные массивы, хранящиеся в базе и содержащие данные с кириллицей, не смогут быть десериализованы средствами PHP, потому что длины строк, указываемые в виде [ s:XX:"текст" ] для cp1251 и для utf-8 различаются. То есть, что было сериализовано под cp1251 нельзя десериализовать под utf-8.
У меня из-за этого слетели описания 3k+ товаров, хранившиеся в свойствах типа html, а также службы доставки, у которых в конфиге была кириллица (а может ещё что-то, чего я не нашёл). Было бы очень круто, если бы скрипт доработали в части конвертации размеров строк в сериализованных массивах, особенно учитывая, что MySQL'ная функция length возвращает в utf'ной базе именно ту длину, которая нужна.
$rs = $DB->Query('SHOW TABLES'); while($f = $rs->Fetch()) { list($k, $table) = each($f); $rs0 = $DB->Query('SHOW FIELDS FROM `'.$table.'`'); while($f = $rs0->Fetch()) { if (!preg_match('#char\(([0-9]+)\)|text#i', $f['Type'], $regs) || $regs[1] <= 10) continue; $rs1 = $DB->Query('SELECT `'.$f['Field'].'` FROM `'.$table.'` WHERE `'.$f['Field'].'` IS NOT NULL AND `'.$f['Field'].'` != "" LIMIT 1'); $f1 = $rs1->Fetch(); list($k, $val) = each($f1); if (unserialize($val) !== false) { echo $table.' '.$f['Field']."\n"; } } }Спасибо за инструкцию и скрипт.
Однако после успешной конвертации в некоторых инфоблоках перед текстовой информацией появились вот такие строки:
a:2:{s:4:"TEXT";s:2202:"
и массив текста закрывается этой строкой:
Видимо никто не ответит, опишу ситуацию.
Дело в том, что Битрикс хранить данные по крайней мере в дополнительных свойствах, следующим образом:
a:2:{s:4:"TEXT";s:2202:" <- заголовок сериализованного массива
То есть эта цифра должна с точностью до знака совпадать с цифрой которая указана в значении второй буквы s.
Если будут расхождения, то будет выводиться все значение VALUE без конвертации сериализованного массива в результате чего вы и получите такой вывод как вы писали.
Короче говоря у вас слетят все доп. поля и настройки инфоблоков, поскольку скрипт который предлагается для конвертации просто конвертирует кодировку в лоб, без пересчёта символов сериализованных масивов, а без этого из полей будет выводиться весь сериализованный массив, а не только данные
Спасибо за ответ. Я так и понял, что это начало и конец массива.
Специально залез в базу после конвертации. В подтверждении Ваших слов, там действительно все данные которые хранились в массиве вида a:2:{...} сами по себе содержаться в массиве вида a:2{...}. И длина там указана с учетом заголовков. Т.е. к примеру, был текст:
a:2:{s:4:"TEXT";s:24:"<h1>HTML-ТЕКСТ</h1>";s:4:"TYPE";s:4:"html";}
После конвертации стало:
a:2:{s:4:"TEXT";s:71:"a:2:{s:4:"TEXT";s:14:"<h1>HTML-ТЕКСТ</h1>";s:4:"TYPE";s:4:"html";}";s:4:"TYPE";s:4:"TEXT";}
Не нашел решения лучше, чем сделать импорт базы в csv, и удалить заголовки и концы массивов с помощью рег.выражений.
Кстати, настройки инфоблоков, почему-то не слетели, как и некоторые доп.поля. Видимо, где-то длина символов осталась верной и, соответственно, правильно указанной в заголовке.
ÐонÑакÑное лиÑо: ÐдминиÑÑÑаÑоÑ
ÐонÑакÑнÑй ÑелеÑон: 02
как это поправить???
выглядит так :
не подскажите ? уже все перепроверил ...
Пересохранение любого инфорблока это исправляет, однако через минуту кодировка слетает по новой.
В чем может быть проблема?
особенно файлы папке Битрикс
пришет База данных работает в кодировке, отличной от cp1251
и не дает еше раз конвертнуть
Начал делать конвертацию на демо версии битрикса редакции Малый бизнес.
После запуска файла convert_utf8.php обрывается обработка ошибкой:
Срок работы пробной версии продукта истек. Вы можете купить полнофункциональную версию продукта на сайте . .
Это нормально для пробной версии или это ошибка скрипта?
Или конвертацию нужно проводить после активации лицензионного ключа?
$connection->queryExecute("SET NAMES 'utf8'";);
$connection->queryExecute('SET collation_connection = "utf8_unicode_ci"');
Тогда получается нужно изменить кодировку на самом сайте, а базу оставить как есть?
Главное в этой истории - поправить параметры соединения (есть два файла в php_interface).
Могу предположить, что добавить какой-то хитрый метод подключения к базе?
в итоге поля такого типа хранятся в бд в формате json, могут находиться либо в общей таблице свойств элементов - b_iblock_element_property, либо в отдельно таблице для данного вида свойства, что-то типа - b_iblock_element_prop_s62, но название может отличаться.
<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); if($USER->IsAdmin()) { $custPropTableName = 'b_iblock_element_prop_s62'; global $DB; $r = $DB->Query("SEL ECT ID FR OM b_iblock_property WHERE USER_TYPE='HTML'"); while($prop = $r->Fetch()) { $rV = $DB->Query("SELECT ID, VALUE FR OM b_iblock_element_property WHERE IBLOCK_PROPERTY_ID=".$prop['ID']." AND VALUE IS NOT NULL AND VALUE LIKE 'a:%'"); while($pV = $rV->Fetch()) { $rowPropVal = $pV['VALUE']; $newJson = getValidJson($rowPropVal); $elID = $pV['ID']; if($newJson && $elID){ $updateSql = "UPD ATE b_iblock_element_property SET VALUE='$newJson' WHERE ID=".$elID; $rs2 = $DB->Query($updateSql); if($rs2){ echo '-updated '.$elID; }else{ echo '-error-update '.$elID; } } echo '<br><br>'; } } $rs = $DB->Query("SELECT * fr om $custPropTableName;"); while($row = $rs->Fetch()) { foreach ($row as $rowPropName => $rowPropVal) { if (strpos($rowPropName, 'PROPERTY_') !== false && strpos($rowPropVal, 'a:') !== false) { $newJson = getValidJson($rowPropVal); $elID = $row['IBLOCK_ELEMENT_ID']; if($newJson && $elID) { $rs2 = $DB->Query("UPDATE $custPropTableName SE T $rowPropName = '$newJson' WH ERE IBLOCK_ELEMENT_ID = $elID LIM IT 1;"); if($rs2) { echo '-updated '.$elID; }else{ echo '-error-update '.$elID; } } echo '<br><br>'; } } } } function getValidJson($rowPropVal) { $str = unserialize($rowPropVal); if($str == false) { /*ПРОБУЕМ СМЕНИТЬ КОДИРОВКУ*/ $encodingIn = mb_detect_encoding($rowPropVal, 'auto'); $rowPropVal = iconv($encodingIn, 'WINDOWS-1251', $rowPropVal); /*ДЕКОДИРУЕМ JSON*/ $str = unserialize($rowPropVal); if($str) { $str['TEXT'] = str_replace(array("'"),'',$str['TEXT']); $arUpdate = array( 'TYPE' => $str['TYPE'], 'TEXT' => iconv('WINDOWS-1251','UTF-8',$str['TEXT']), ); /*КОДИРУЕМ В JSON В НОВОЙ КОДИРОВКЕ*/ $newJson = serialize($arUpdate); return $newJson; } } return false; } require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>У вас указано, что скрипт выполняет два действия:
- Конвертировать все файлы в utf8
- Конвертировать БД в utf8
Но у меня только конвертируется БД, а файлы сайта остаются в том же виде и тоже кодировке.
Почему так происходит и как это можно поправить?
Помогите пожалуйста решить загвостку.
Заранее спасибо за ответ и помощь!