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

Помощь пользователям в работе с программой E-Trade PriceList Importer
Ответить
Аватара пользователя
TechAdmin
Администратор
Сообщения: 4286
Зарегистрирован: 27 авг 2008 14:30

02 ноя 2009 14:34

Если у вас проблема отображения букв кириллицы при импорте из 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; $data=fgetcsv($f,1000,"\t"); $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 этот файл в корневую папку и запустить на выполнение http://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) необходимо выполнить:


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

Код: Выделить всё

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"
LC_ALL=


Это означает что кодировка в консоли используется 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"
LC_ALL=


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

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

Код: Выделить всё

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 попробуйте найти в сети интернет.
С уважением, поддержка ElbuzGroup.
Ответить

Вернуться в «Техническая поддержка программы E-Trade PriceList Importer»