Проблема отображения букв кириллицы при импорте из CSV файла

Navigation:  Возможные проблемы и решения для их устранения >

Проблема отображения букв кириллицы при импорте из CSV файла

Previous pageReturn to chapter overviewNext page

Если у вас проблема отображения букв кириллицы при импорте из CSV файла в ваш интренет-магазин с использованием нашего модуля экспорта и импорта данных, тогда это описание проблемы может помочь вам в его решении. Данная пробема проявляется в частичном отображении букв кириллицы. Связаная она с настройками локали на используемом хостинге. Для импорта данных из файла CSV необходима локаль ru_RU.cp1251, т.к. экспортный файл из программы обработки прайсов E-Trade PriceList Importer экспортируется в кодировке win-1251.

 

Почему функции работы со строками не работают с «русскими буквами», т.е. с кириллицей?

При обработке текстов, содержащих символы кирилицы («русские буквы»), с помощью функций: fgetcsv(), strToLower(), strToUpper(), preg_match() и т. п., в некоторых случаях может наблюдаться некорректная работа указанных функций. Собственно проблема возникает тогда, когда кодировка сайта отличается от кодировки, используемой PHP-интерпретатором по умолчанию.

 

На сегодняшний день наиболее популярной кодировкой является кодировка UTF-8, позволяющая в одном документе использовать символы различных языков, например сочетать символы кирилицы и китайские, греческие символы на одной странице. Однако для «старых» русскоязычных сайтов характерно использование кодировки windows-1251 (CP1251). В тех случаях когда сайт с кодировкой CP1251 запускается на web-сервере, использующем по умолчанию кодировку UTF-8, а вместе с web-сервером эту же кодировку по умолчанию будет использовать и PHP-интерпретатор, наблюдается некорректная работа некоторых функций PHP, используемых для обработки текста. Так же на хостинге может не работать, а на Windows Apache (localhost) дома все хорошо, если это так, то это явная проблема настроек локали хостинга.

 

Решением возникающей проблемы является явное указание настроек локализации, в частности кодировок, которые должен использовать PHP-интерпретатор, которое производится с помощью функции setLocale().

 

Ниже приводится пример использования функции setlocale():

<?php
setlocale(LC_ALL, 'ru_RU.CP1251');
echo strtoupper('Проблема с кириллицей решена! The problem with the Cyrillic solved!');
?>

 

 

 

Описание функции setlocale из справки языка PHP.

 

setlocale - устанавливает локальную информацию.

 

Описание

string setlocale (mixed category, string locale)

Category это именованная константа (или строка), специфицирующая категорию функций, на которые действуют локальные установки:

 

* LC_ALL - все ниже указанные

* LC_COLLATE - сравнение строк, см. strcoll()

* LC_CTYPE - классификация и конвертация символов, например, strtoupper()

* LC_MONETARY - localeconv()

* LC_NUMERIC - десятичный сепаратор (см. также: localeconv())

* LC_TIME - форматирование даты и времени с помощью strftime()

 

 

Если locale это пустая строка "", название локализации будет установлено из значений переменных окружения с теми же именами, что и вышеуказанные категории, или из "LANG".

Если locale равен нулю или "0", локальные установки не меняются, только возвращаются текущие установки.

Setlocale возвращает новую текущую локализацию, или FALSE, если locale-функциональность не реализована на данной платформе, специфицированная locale не существует или имя категории неправильное. Неправильное имя категории вызывает также появление предупреждающего сообщения.

 

Пример 2. setlocale()

<?php

   /* установить locale Dutch */

   setlocale (LC_ALL, 'nl_NL');

 

   /* на выходе: vrijdag 22 december 1978 */

   echo strftime ("%A %e %B %Y", mktime (0, 0, 0, 12, 22, 1978));

?>

 

Пример 3. Простой пример кода с использованием функции fgetcsv() для разбора строк и колонок CSV файла. Как раз данная функция используется при работе нашего модуля импорта и экспорта данных.

$f = fopen("e-trade.csv", "rt") or die("Ошибка!");

for ($i=0; [b]$data=fgetcsv($f,1000,"\t");[/b] $i++)

{  $num = count($data);

echo "<h3><FONT class=mid_2>Строка номер $i (полей: $num):</h3>";

for ($c=0; $c<$num; $c++)  

print "[$c]: $data[$c]<br>";

}

fclose($f);

 

Содержимое файла e-trade.csv:

dress;read;100

тошиба;read;200

the cars;read;300

the cars;лучший;300

ноутбук;лучший;100

телевизор_WQбольшой;;

 

При выводе на страницу в отладочном режиме PHP отображается в таком виде, (нет кириллицы):

   Строка номер 0 (полей: 3):

   [0]: dress

   [1]: read

   [2]: 100

 

   Строка номер 1 (полей: 3):

   [0]:

   [1]: read

   [2]: 200

 

   Строка номер 2 (полей: 3):

   [0]: the cars

   [1]: read

   [2]: 300

 

   Строка номер 3 (полей: 3):

   [0]: the cars

   [1]:

   [2]: 300

 

   Строка номер 4 (полей: 3):

   [0]:

   [1]:

   [2]: 100

 

   Строка номер 5 (полей: 3):

   [0]: _WQбольшой

   [1]:

   [2]:

 

Для проверки локализации которая используется для работы PHP используйте маленький код:

   <?php

   print "Проверка чтения CSV файла<br>";

   echo("Locale=".setLocale(LC_ALL, NULL));

   ?>

 

Вы можете создать файл testLocale.php в него переписать этот код, закачать по ftp этот файл в корневую папку и запустить на выполнение https://your_site/testLocale.php, результатом выполнения на хостинге может быть такой результат:

Проверка чтения CSV файла

Locale=C

 

а на домашнем "денвере" (джентльменский набор Web-разработчика, «Д.н.w.р», читается «Денвер») возвращает:

Проверка чтения CSV файла

Locale=Russian_Russia.1251

 

Если после попытки установить нужную локаль в коде ничего не происходит, т. е. локаль не устанавлиется, значит она не стоит на сервере (типично для забугорных хостингов). Если у Вас есть рутовый доступ к серверу - ставите нужную локаль на сервер (инструкция как это делать написана ниже), в противном случае пишите в суппорт хостеру просьбу добавить нужную локаль.

 

 

 

Настройка локали в консоли в ОС Linux CentOS.

 

Довольно часто владельцы выделенных серверов получают свои сервера от хостинг провайдеров с неверно сконфигурированной локалью или не донастроенной для "старой" кодировки 1251. В следствии чего в консоли или при работе скриптов PHP не отображаются русские буквы или отображаются не корректно. Так как CentOS практически является клоном RedHat Enterprise Linux, то консоль по умолчанию использует кодировку UTF-8, то есть юникод. Постепенно кодировка юникод(UTF-8) вытесняет кучу "наших" кодировок, например KOI8-R, CP1251.

 

Для того чтобы проверить какая локаль сейчас установлена в системе можно использовать команду locale, для этого в консоли сервера (ssh) необходимо выполнить:

locale

 

обычный вывод команды примерно такой:

LANG=en_US.UTF-8

LC_CTYPE="en_US.UTF-8"

LC_NUMERIC="en_US.UTF-8"

LC_TIME="en_US.UTF-8"

LC_COLLATE="en_US.UTF-8"

LC_MONETARY="en_US.UTF-8"

LC_MESSAGES="en_US.UTF-8"

LC_PAPER="en_US.UTF-8"

LC_NAME="en_US.UTF-8"

LC_ADDRESS="en_US.UTF-8"

LC_TELEPHONE="en_US.UTF-8"

LC_MEASUREMENT="en_US.UTF-8"

LC_IDENTIFICATION="en_US.UTF-8"

 

Это означает что кодировка в консоли используется en_US.UTF-8. Так же вывод может совсем иначе выглядеть, например так:

LANG=

LC_CTYPE="POSIX"

LC_NUMERIC="POSIX"

LC_TIME="POSIX"

LC_COLLATE="POSIX"

LC_MONETARY="POSIX"

LC_MESSAGES="POSIX"

LC_PAPER="POSIX"

LC_NAME="POSIX"

LC_ADDRESS="POSIX"

LC_TELEPHONE="POSIX"

LC_MEASUREMENT="POSIX"

LC_IDENTIFICATION="POSIX"

 

Это сигнализирует что есть проблемы.

 

Для того чтобы проверить наличие готовых локалей в системе необходимо выполнить команду:

locale -a | grep ru

 

В выводе команды необходимо найти необходимую нам локаль. В случае с кодировкой UTF-8 необходимая локаль имеет вид ru_RU.utf8. Если такая строка есть в выводе команды, тогда необходимо сделать следующее действия:

Создаем файл /etc/sysconfig/i18n командой:

touch /etc/sysconfig/i18n

 

После чего в файл пишем следующие строки:

LANG="ru_RU.UTF-8"

SUPPORTED="ru_RU.UTF-8:ru_RU:ru"

SYSFONT="latarcyrheb-sun16"

 

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

 

Если же при выводе команды

   locale -a | grep ru

 

нет русской локали, тогда ее необходимо установить. Команда для установки локали:

localedef  -i ru_RU -f UTF-8 ru_RU.UTF-8

 

Данная команда, она берет из стандартной папки /usr/share/i18n/locales/файл ru_RU (это файл с описанием русской локали) и из папки /usr/share/i18n/charmaps  файл UTF-8.gz (это символьная карта для описания юникода) и на основе этих файлов генерирует нужную нам локаль ru_RU.UTF-8.

После этого действия в системе появляется нужная локаль, а дальше необходимо сделать так как описано абзацом выше.

 

Если у вас нет файлов в папке /usr/share/i18n/, то необходимо разбираться с самим glibc-common, это отдельная статья, поэтому информацию об glibc-common попробуйте найти в сети интернет.