Если у вас проблема отображения букв кириллицы при импорте из 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 попробуйте найти в сети интернет.