Проблема с отображением русских букв в браузере, даже если установлена ​​кодировка UTF-8 - PullRequest
2 голосов
/ 23 августа 2011

Мне известно, что были некоторые похожие проблемы. Однако после прочтения ответов и бреда по теме я все еще пытаюсь отобразить русские буквы в браузере. Я храню их в файле .csv (который закодирован в UTF-8 без спецификации). В моем php-файле, который читает .csv (который также закодирован в UTF-8 без спецификации), я объявил charset:

 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Для открытия и просмотра файла .csv я использую следующий код:

  if(($handle = fopen($path, "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
      ...
    }
  }

и либо ничего не отображается, либо что-то вроде этого:

 -ам-Зее

вместо

 Целль-ам-Зее

Есть идеи, что еще я могу попробовать?

UPDATE:

После настройки кодировки браузера на UTF-8 я получаю правильные русские буквы. Тем не менее, часть текста вообще не отображается. Я подозреваю, что я что-то делаю неправильно, читая файл .csv, упрощенная версия:

     if(($handle = fopen($path, "r")) !== FALSE) {
       while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
         echo $data[1];
        }
     }

(я опускаю первый столбец и отображаю содержимое второго, который всегда заполнен)

Ответы [ 2 ]

5 голосов
/ 23 августа 2011

Проверьте конфигурацию вашего сервера

У вас есть Apache, сконфигурированный для поддержки переопределения кодировки <meta>?По умолчанию он использует ISO-8859-1 в качестве значения по умолчанию и игнорирует все переопределения, которые появляются на веб-страницах, которые он обслуживает.

Решение № 1 из 3

Например,вы можете поместить это в файл .htaccess для вложенного каталога, и теперь ваши веб-страницы будут иметь свои переопределения <meta>:

AddDefaultCharset Off
AddCharset UTF-8 .html

Документация Apache гласит:

Эта директива задает значение по умолчанию для параметра набора символов типа носителя (имя кодировки символов), которое будет добавлено к ответу, если и только если content-type ответа равен либо text/plain, либоtext/html.Это должно переопределить любой набор символов, указанный в теле ответа через элемент META, хотя точное поведение часто зависит от конфигурации клиента пользователя.Настройка AddDefaultCharset Off отключает эту функцию.AddDefaultCharset On включает кодировку по умолчанию iso-8859-1.Предполагается, что любое другое значение будет использоваться как набор символов, который должен быть одним из зарегистрированных значений IANA *1027* для использования в типах носителей MIME.Например:

   AddDefaultCharset utf-8     

AddDefaultCharset следует использовать только тогда, когда известно, что все текстовые ресурсы, к которым он применяется, находятся в этой кодировке символов, и слишком неудобно маркировать их кодировку по отдельности.Одним из таких примеров является добавление параметра charset к ресурсам, содержащим сгенерированный контент, например к устаревшим CGI-сценариям, которые могут быть уязвимы для атак с использованием межсайтовых сценариев из-за того, что предоставленные пользователем данные включаются в выходные данные.Однако обратите внимание, что лучшим решением является просто исправить (или удалить) эти сценарии, поскольку установка кодировки по умолчанию не защищает пользователей, которые включили функцию «автоопределение кодировки символов» в своем браузере.

Пока я не выключил AddDefaultCharset, я не мог заставить свои <meta> теги работать.Это было довольно таинственно и неприятно.Как только я это сделал, все работало гладко.

Решение № 2 из 3

Если у вас есть права на запись в файлы конфигурации Apache, вы можете изменить сам сервер.Тем не менее, вы должны убедиться, что ничто другое не зависит от старого неопределяемого параметра.Это еще одна причина для использования .htaccess.


Когда все остальное терпит неудачу: Решение № 3 из 3

Если вы не можете ни изменить общую конфигурацию сервера, ни создать .htaccess чьи собственные настройки будут соблюдаться для всего, что находится под ним, тогда единственный вариант - использовать числовые объекты для всех кодовых точек более 127. Например, вместо

Целль-ам-Зее

вместо этого необходимо использовать

&#1062;&#1077;&#1083;&#1083;&#1100;-&#1072;&#1084;-&#1047;&#1077;&#1077;

или

&#x426;&#x435;&#x43B;&#x43B;&#x44C;-&#x430;&#x43C;-&#x417;&#x435;&#x435;

Преимущество этого состоит в том, что он больше не требует переопределения и манипуляции с сервером <meta> или файлами .htaccess.Недостатком является то, что для этого требуется дополнительный этап перевода, что препятствует возможности прямого редактирования файла с помощью редактора, понимающего литерал UTF ‑ 8.

Сущности игнорируют кодировки

Причина, по которой это работаетпотому что весь HTML всегда находится в Unicode, поэтому номер 1062 всегда CYRILLIC CAPITAL LETTER TSE и т. д. Номера объектов всегда представляют номера кодовых точек Unicode;они никогда не являются числами из кодировки документа.Только закодированные байты считаются находящимися в кодировке сервера или страницы, а не незашифрованные номера кодовых точек, которые всегда являются Unicode.

Вот почему мы можем использовать что-то вроде &#233;, и это всегда означает LATIN SMALL LETTER E WITH ACUTE, поскольку кодовая точка 233 всегда является этим символом, даже если сама веб-страница должна быть в другой кодировке (например, 142 в MacRoman или 221 в NextStep).

номерs символов всегда являются номерами Unicode и не обращают внимания на кодировку.Это связано с тем, что языки разметки, такие как HTML, XHTML и XML, всегда используют логические номера кодов Unicode, как это делают языки программирования, такие как Perl и Go.(PHP - это всего лишь байты с некоторыми API-интерфейсами UTF ‑ 8, но, как вы уже поняли, с ним все еще остаются проблемы. Это связано как с его внутренней моделью, так и с веб-серверами и даже веб-клиентами,все это делает все более сложным в PHP, чем в большинстве других языков.)

Даже если вы закодировали свою веб-страницу в ISO-8859-1 для кириллицы, где буквенный байт 0xC6 кодирует Unicode U + 0426,CYRILLIC CAPITAL LETTER TSE, в качестве символьной сущности вы бы использовали &#1062; или &#x426; - а не &#xC6;, что было бы неправильно, поскольку U + 00C6 равно LATIN CAPITAL LETTER AE.

Аналогично, если бы вы использовали кодировку MacCyrillic, литеральный байт 0x96 был бы CYRILLIC CAPITAL LETTER TSE, но поскольку числовой объект всегда находится в Юникоде, вы должны использовать &#1062; или &#x426; - а не&#x96;.

Я предпочитаю использовать только UTF ‑ 8 для всех веб-страниц.Ну, для новых, то есть.Я признаю, что существуют устаревшие не-Unicode страницы.Те, кого я оставляю как есть.

4 голосов
/ 23 августа 2011

Вам необходимо установить правильный языковой стандарт на вашем сервере.

if(!setlocale(LC_ALL, 'ru_RU.utf8')) 
    setlocale(LC_ALL, 'en_US.utf8');

И затем вы можете проверить, принял ли ваш сервер необходимый языковой стандарт

if(setlocale(LC_ALL, 0) == 'C')
    echo 'Error setting locale';

Проблема в функции fgetcsv, котораяиспользует неправильную локаль.Если у вас нет возможности изменить локаль, вы можете заменить функцию fgetcsv своей собственной командой explode

...