Неправильная кодировка сайта (крокозябры или абракадабра)

Неправильная кодировка сайта (крокозябры или абракадабра)

«правильная» utf-8 кодировка в настройках nginx/apache

Неправильная кодировка сайта (крокозябры или абракадабра)

Надеюсь, что данный пост окажется полезным многим разработчикам, т.к. судя по многочисленным тредам в интернете, проблема-то довольно частая. Суть проблемы в следующем: неправильное наименование кодировки utf-8 в настройках nginx/apache. При этом отдаваемый сервером контент воспринимается нормально во всех браузерах, кроме Internet Explorer-a.

Зачастую, многие разработчики, при конфигурации виртуальных хостов копируют настройки откуда-нибудь из интернета или же из других мест. И при этом в их настройки «перекочевывает» ошибка. В случае nginx это директива:

charset utf8;

В случае Apache это:

<Directory /path/to/site/>
AddDefaultCharset UTF8
</Directory>

Так вот — нет такой кодировки как

utf8

! Правильно писать

utf-8

(через дефис). Большинство браузеров (Firefox >= 3, Opera >= 9, Chrome >= 4, Safari >= 4) лояльно относятся к указанию

utf8

в качестве кодировки, и воспринимают отдаваемый контент корректно, а вот все версии

Internet Explorer

(включая даже последнюю, 9ую) вместо контента выдают «кракозябры». Конечно же эта ситуация легко обходится даже без исправления настроек web-сервера. Так, например, в случае отдачи динамического контента с использованием PHP, можно явно указывать кодировку в самом скрипте:

header(‘Content-type: text/html; charset=utf-8’);

Или же использовать в HTML следующий тег:

<metahttp-equiv=”content-type”content=”text/html; charset=utf-8″/>

И все бы хорошо, но ситуация усложняется когда посредством AJAX JavaScript пытается достучаться до статического контента. Пример с использованием jQuery:

$(document).ready(function(){
function print_r()
{
//…
}
$.ajax({
url: “/test.txt”,
dataType: “text”,
success: function(data, textStatus){
$(‘#res’).html(data);
},
error: function(jqXHR, textStatus, errorThrown) {
$(‘#res’).html(‘jqXHR: ‘ print_r(jqXHR) ‘<br />textStatus: ‘ textStatus ‘<br />errorThrown: ‘ print_r(errorThrown));
}
});
});

В данном случае IE выдает ошибку следующего характера:

{
jqXHR: {
readyState: 4,
status: 0,
statusText: ‘error’
},
textStatus: ‘error’,
errorThrown: {
name: ‘Error’,
number: -1072896658,
description: ‘Не удалось завершить действие. Ошибка c00ce56e.’,
message: ‘Не удалось завершить действие. Ошибка c00ce56e.’
}
}

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

P.S. Как было верно подмечено в комментариях, при обращении к MySQL для указания в какой кодировке обращаться к БД используется запрос:

SET NAMES utf8

Да и вообще везде, где идет ссылка на кодировку utf-8, например при создании таблицы:

CREATE TABLE `some_table` (… ) ENGINE=innoDB DEFAULT CHARSET=utf8

кодировка указывается utf8, а не utf-8. То есть в данном случае запись идет БЕЗ дефиса, что вносит ещё больший когнитивный диссонанс в понимание происходящего…

Проблема кодировки при работе с базой данных

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

Не будем ничего изменять в настройках и при создании БД и таблицы оставим все как есть, т.е. будет использована кириллическая кодировка. Хотя, забегая вперед, можно сказать, что если бы мы создали таблицы в нужной нам кодировке, то это совсем не означает, что данные будут выведены в этой же кодировке… вся хитрость в том, что здесь существует такой параметр, как кодировка соединения с БД. Вот ее то мы и будем использовать для достижения нужного результата.

Итак, создадим файл с кодировкой юникод (поскольку мы заранее знаем, что данные из БД будут выведены в кириллической кодировке), т.е. мы таким образом поставили перед собой в учебных целях проблему, которую и попытаемся решить… как говорится, тяжело в учении… :)

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

Теперь создадим БД charset и в ней таблицу test с двумя полями:

id, тип INT, первичный ключ, автоинкремент;

text, тип VARCHAR, длина 255.

В таблицу поместим единственную запись в поле text:

Эту запись мы и будем выводить на экран. Для этого пропишем соединение с сервером MySQL, выберем БД для работы и запросом выберем необходимые данные (все это мы уже проделывали в ряде предыдущих уроков, а потому подробно останавливаться на объяснении всего этого — нет оснований):

Теперь в массиве $row мы имеем искомую строку. Давайте выведем ее в теле страницы (между тегами body):

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

Пропишем необходимый запрос после соединения:

Теперь после обновления страницы информация выводится корректно.Вот и вся хитрость.

Utf-8

Unicode Transformation Format — универсальный стандарт кодирования, который работает с символами почти всех языков мира. Символы могут занимать от 1 до 4 байт, такое кодирование позволяет создавать мультиязычные сайты.

Сейчас ищут техподдержку:  Договор на техническое обслуживание сайта

Есть несколько вариантов — UTF-8, 16, 32, но чаще используют восьмибитное.

Windows-1251

Этот вид занимает второе место по популярности после UTF-8. Windows-1251 — кодирование для кириллицы, созданное на базе кодировок, использовавшихся в русификаторах операционной системы Windows. В ней есть все символы, которые используются в русской типографике, кроме значка ударения. Символы занимают 1 байт.

Выбор кодировки остается на усмотрение веб-мастера, но UTF-8 используют намного чаще — ее поддерживают все популярные браузеры и распознают поисковики, а еще ее удобнее использовать для сайтов на разных языках.

Определить кодировку страницы своего или чужого сайта можно через исходный код страницы. Откройте страницу сайта, выберите «Просмотр кода страницы» (сочетание горячих клавиш Ctrl U» в Google Chrome) и найдите упоминание «charset» внутри тега head.

На странице сайта используется кодировка UTF-8:

Как посмотреть, какая кодировка на сайте
Указание кодировки в коде страницы

Узнать вид кодирования можно с помощью «Анализа сайта». Сервис проверяет в том числе и техническую сторону ресурса: анализирует серверную информацию, определяет кодировку, проверяет редиректы и другие пункты.

Как определить кодировку на сайте
Фрагмент анализа серверной информации сайта

С помощью этого же сервиса можно проверить корректность указанного кодирования. Аудит внутренних страниц «Анализа сайта» проверяет кодировку сервера и сравнивает ее с той, которая указана на внутренней странице. Найденные ошибки Анализ покажет в результатах проверки, и вы сразу узнаете, где нужно исправить.

Проверка кодировки на сайте
Отчет о технических данных

Проверить кодировку еще можно через сервис Validator.w3, о котором писали в статье о проверке валидации кода. Нужная надпись находится внизу страницы.

Сервис для проверки кодировки на сайте
Кодировка сайта в валидаторе

Если валидатор не обнаружит Charset, он покажет ошибку:

Некорректная кодировка, пример
Ошибка указания кодировки

Но валидатор работает не точно: он проверяет только синтаксис разметки, поэтому может не показать ошибку, даже если кодирование указано неправильно.

Вариант номер 1 .htaccess

Причина: Все адекватные инструменты web-разработчика работают с кодировкой UTF-8, но, например, Денвер (по умолчанию) настрое на кодировку windows-1251 (CP1251). 

Решение: Необходимо в найти в корне своего сайт файл .htaccess, если его нет – создать и написать в нем AddDefaultCharset UTF-8 . Если файл уже существует – добавьте эту строку в начале или конце файла.

Вариант номер 2 sublim text другие ide

Причина: если вы еще не определились с редактором (IDE), в котором пишите код – вас ждет неприятный сюрприз. Вы, сначала, в Sublim text открыли файл, который создали в Блокноте, потом запустили какой-то Brackets и т.д. Я предпочитаю NetBeans Gedit.

Решение: Если проект небольшой – открываете все файлы с кодом в Notepad и заходите в пункт меню “Кодировка (Encoding)”, здесь вы увидите кодировку своего файла. Если у вас установлена не UTF-8 (UTF-8 без BOM) – выбираете пункт “Преобразовать в UTF-8 (Convetr to UTF-8)” и сохраняете файл. Благо, что такая проблема встречается крайне редко.

Виды кодировок

Существует довольно много видов, но сейчас распространены два:

Где указать кодировку сайта

Если проблема возникла на вашем сайте, способ исправления зависит от вида сайта. Для одностраничника достаточно указать кодировку в мета-теге страницы, а для большого сайта есть разные варианты:

  • кодировка в мета-теге;
  • кодировка в .htaccess;
  • кодировка документа;
  • кодировка в базе данных MySQL.

Если кодировка не отображается

Если вы зашли на чужой сайт с абракадаброй, а вам все равно очень интересно почитать контент, то в Справке Google объясняют, как исправить кодирование текста через браузер.

О проблеме возникновения абракадабры на вашем сайте будут сигнализировать метрики поведения: вырастут отказы, уменьшится глубина просмотров. Но скорее всего вы и раньше заметите, что что-то пошло не так.

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

Зачем нужна кодировка

Кодировка (Charset) — способ отображения кода на экране, соответствие набора символов набору числовых значений. О ней сообщает строка Content-Type и сервер в header запросе.

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

На сайте слетела кодировка, пример
Студентка списывала реферат с формулами, а на сайте слетела кодировка. Реальная история

Google рекомендует всегда указывать сведения о кодировке, чтобы текст точно корректно отображался в браузере пользователя.

Как создать файл .htaccess в windows

Если вас “угораздило” быть пользователем Windows, вы узнаете, что невозможно в ОС Win создать файл, у которого нет имени и расширение из восьми символов)) именно таким является файл .htaccess. Как же создать файл .htaccess в Windows? Вот самый простой способ из подручных средств:

Стоит сразу пояснить почему не рекомендую запускать “Блокнот”. Блокнот сохраняет в кодировке windows-1251, если у вас появится дурная привычка использовать “Блокнот” для быстрого редактирования файлов – будет постоянно путаться кодировка.

Кодировка базы данных

Выбирайте нужную кодировку сразу при создании базы данных. Распространенный вариант — «UTF-8 general ci».

Где менять кодировку у БД:

Кодировка в мета-теге

Добавьте указание кодировки в head файла шаблона сайта.

Сейчас ищут техподдержку:  Не работает сайт | | Компания «LRC» — «Lease Realty Concepts» — международная компания, оказывающая профессиональные услуги в сфере коммерческой недвижимости.

При создании документа HTML укажите тег meta в начале в блоке head. Некоторые браузеры могут не распознать указание кодировки, если оно будет ниже.

Мета-тег может выглядеть так:

Кодировка влияет на seo?

Разберемся, как кодировка на сайте влияет на индексацию в Яндекс и Google.

Яндекс четко заявляет:

«Тип используемой на сайте кодировки не влияет на индексирование сайта. Если ваш сервер не передает в заголовке кодировку, робот Яндекса также определит ее самостоятельно».

Позиция Google такая же. Поисковики не рассматривают Charset как фактор ранжирования или сигнал для индексирования, тем не менее, она косвенно влияет на трафик и позиции.

Если кодировка сервера не совпадает с той, что указана на сайте, пользователи увидят нечитабельные символы вместо контента. На таком сайте сложно что-либо понять, так что скорее всего пользователи сбегут, а на сайте будут расти отказы.

Некорректно указана кодировка на сайте
Пример страницы со слетевшей кодировкой

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

Кодировка документа

Готовые файлы HTML важно сохранять в нужной кодировке сайта. Узнать текущую кодировку файла можно через Notepad : откройте файл и зайдите в «Encoding». Меняется она там же: чтобы сменить кодировку на UTF-8, выберите «Convert to UTF-8 without BOOM».

Решаем проблемы с кодировкой на сайте.

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

Во-первых, настоятельно рекомендую, чтобы все документы были в одной кодировке и база данных, а именно поля со строковыми данными, имели такую же кодировку. Устанавливается она при создании базы или же можно указывать сравнение для каждого отдельного поля. Если создаёте БД с помощью phpMyAdmin, то сложностей возникнуть не должно: закладка “Базы данных” > в поле под “Создать базу данных” вписываете имя вашей будущей БД > рядом выпадающий список “Сравнения”. Если же создаёте базу sql-запросом, то пишите примерно следующее:

CREATE DATABASE IF NOT EXISTS `my_db_name` CHARACTER SET utf8 COLLATE utf8_general_ci;

Выбор кодировки остаётся за вами, но я бы посоветовал выбрать для документов “UTF-8 без BOM” и сравнение для базы “utf8_general_ci” (юникод многоязычный, регистронезависимый). Только не забудьте подстраховаться и сделать дамп перед манипуляциями с БД! Не буду здесь расписывать, что такое BOM, но если о-о-очень образно и на пальцах, то это такой невидимый маркер, который планировался для различения кодировок UTF-16LE и UTF-16BE, но по некоторым причинам оказался невостребованным и теперь мешает веб-разработчикам жить спокойно 😉 Выглядит BOM, как символ U FEFF и селится в начале документа. А почему всё-таки UTF-8? Вот, хотя бы пара причин… Вы без проблем сможете выводить на экран как кириллицу, так и цитату из стихов Аль-Мутанабби или китайские иероглифы. Всё потому, что в той же кодировке windows-1251 (cp1251) всего лишь 256 символов, в то время, как в UTF-8 их около ста тысяч, плюс ко всему специальные символы, пиктограммы, значки и т.д. Если вы собираетесь использовать на своём сайте ajax-запросы, то это так же добавляет плюс к кодировке UTF-8, потому что именно с этой кодировкой дружит объект XMLHttpRequest, а с другими придётся извращаться и иногда безуспешно. Та же карта сайта (sitemap.xml), которая служит для индексации поисковыми системами, работает только, если этот файл создан с кодировкой UTF-8. Кроме того, эта кодировка является стандартом для работы многих функций PHP и стандартом, который рекомендован W3C.

При создании нового документа – всё ясно, а как быть с уже существующим, в котором желательно изменить кодировку? Один из самых простых способов – это открыть документ в Notepad , выбрать в меню “Кодировки” и в списке “Преобразовать в UTF-8 без BOM“. Далее изменяем метатег с определением кодировки:

<meta charset="utf-8"><!-- для HTML5 (рекомендуется) -->
<!-- или -->
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"><!-- для более старых версий HTML -->

И для php-файлов можно установить соответствующий заголовок, но только, если файл не подключен в другом документе, где такой заголовок уже будет отправлен раньше. Это касается как заголовка в метатеге, так и отправленного функцией header:

header('Content-Type: text/html; charset=utf-8');

Проверяем результат в браузере. Тут может несколько вариантов:

  1. Всё выводится отлично и вопрос закрыт
  2. Статически прописанные данные отображаются нормально, но данные из БД – всё тами же “кракозябрами”
  3. Ничего не изменилось и кодировка осталась кривой

Начнём с последнего пункта. Счастливые владельцы выделенных серверов или VPS/VDS, могут изменить кодировку для директивы default_charset в конфигурационном файле php.ini. Тем же, кто доступа к php.ini не имеет или имеет, но необходимо изменить кодировку только для одного сайта, можно использовать файл .htaccess, записав в него следующее:

# в принципе, хватает строки ниже:
AddDefaultCharset UTF-8
# но иногда, могут потребоваться дополнительные установки:
DefaultLanguage ru
php_value default_charset "utf-8"

Файл .htaccess распологается в корне вашего сайта. Если вы его там не обнаружили, то создаём сами. В обычном блокноте создаёте документ > “Сохранить как” > Тип файла выбрать “Все файлы” > в поле “Имя файла” записываем только точку и расширение “.htaccess“.

Сейчас ищут техподдержку:  Горячая линия гибдд новосибирска бесплатно круглосуточно

Переходим ко второму пункту – если базу перевели на нужную кодировку, но данные из неё отображаются на странице криво. Для начала, нужно убедится, что символы в самой базе отображаются нормально. Если кодировка там “не поплыла”, то можно или же опять апеллировать к файлам конфигурации, или сделать запрос сразу после подключения к базе:

SET NAMES utf8;

*я пишу сам текст запроса, но т.к. не знаю какое расширение вы используете для работы с MySQL, покажу несколько вариантов:

// для устаревшего mysql_*
$db = mysql_connect('localhost', 'username', 'password');
mysql_select_db('db_name', $db);
mysql_query('SET NAMES utf8');

// для PDO и версий php ниже 5.3.6
$dbh = new PDO('mysql:host=localhost;dbname=db_name', 'username', 'password');
$dbh->exec('SET NAMES utf8');
// для PDO и версий php 5.3.6 и новее, можно указывать прямо при создании объекта
$dbh = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8', 'username', 'password');
// или 
$db = new PDO('mysql:host=localhost;dbname=db_name', 'username', 'password', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

// для MySQLi
$mysqli = new mysqli('localhost', 'username', 'password', 'db_name');
$mysqli->set_charset("utf8");

Раз уж затронул вопрос “устаревшего mysql_*”, то хочу обратить ваше внимание, на текст выделенный красным в документации php. Cто́ит задуматься…
Если у вас была одна из стандартных проблем, то выполнив некоторые или все вышеописанные шаги, с кодировкой вопрос будет решен положительно. Но так же хотелось бы упомянуть о некоторых функциях, которые могут пригодится в нестандартных ситуациях. Подробнее о них вы сможете прочитать в документации, а я лишь приведу пару примеров, не вдаваясь в подробности:

mb_internal_encoding()
C помощью этой функции, мы можем установить или получить текущую кодировку скрипта:

mb_internal_encoding('UTF-8'); // устанавливаем
echo mb_internal_encoding(); // без аргумента - получаем
mb_http_input() и mb_http_output()
Две функции, которые определяют, устанавливают или получают кодировку символов HTTP запроса или вывода:

print_r( mb_http_input('I') ); // определяем кодировку входных данных http-запроса
mb_http_output('UTF-8');  // устанавливаем кодировку для http-вывода
echo mb_http_output();  // получаем текущую кодировку символов http-вывода
iconv()
Функция преобразовывает символы строки в нужную кодировку:

echo iconv('utf-8','cp1251','Привет, РјРёСЂ!'); // Привет, мир!
mb_convert_encoding()
Функция похоже на iconv(), но на мой взгляд лучше, т.к. работает более адекватно.

echo mb_convert_encoding('Привет, РјРёСЂ!','cp1251','utf-8'); // Привет, мир!

Да и вообще, не забываем про аналоги функций для работы с многобайтными строками. Чаще всего, они имеют такое же название, но с приставкой mb_. Разницу ощутить достаточно просто. Возьмём, для примера, функции strlen() и mb_strlen() и проведём эксперимент, измерив длину строки:

// установим внутреннюю кодировку
mb_internal_encoding('utf-8');

// для латинских символов разницы нет
echo strlen('incode'); // 6
echo mb_strlen('incode'); // 6

// А вот с кириллицей выдает - пичалька
echo strlen('инкод'); // 10
echo mb_strlen('инкод'); // 5

Может кому и не нужно объяснять это явление, но для новичков растолкую: кириллица кодируется двумя байтами, а strlen() считает именно количество байт в строке, а не количество букв. Вот и получается, что пять кириллических символов умножить на два – получаем 10. Китайские символы, если я не ошибаюсь, вообще кодируются тремя байтами, поэтому в дальнейшем для таких случаев, чтоб не возникало никаких недорозумений, используйте соответствующие функции.


Повторюсь, что эти решения к часто встречающимся случаям и в подавляющем большинстве, они решают проблему. Но если у вас возникла ситуация, когда всэ эти способы не возымели действия, то пишите сюда, попробуем разобраться вместе и дополним статью новым “рецептом от головной боли” 😉 Засим позвольте откланяться.

Заключение

Стоит обратить внимание на отличия в именовании кодировок в MySQL от традиционного их именования, т.е. того, к которому мы привыкли. Например, указать юникод правильно так — “utf8”, но не так — “utf-8”. Второй вариант серверу MySQL будет непонятен. Аналогично с кириллицей: правильно так — “cp1251”, но не так — “windows-1251”.

На этом наш урок подходит к концу. Теперь, если Вы будете использоваться в своей работе озвученные выше правила, то проблем с кодировками у вас будет гораздо меньше.

Надеюсь, данный урок был полезен для Вас. Если у Вас остались какие-либо вопросы, то я с удовольствием отвечу на них в комментариях.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 4,00 из 5)
Загрузка...

Оставьте комментарий

Adblock
detector