Кодировки сайта: проблемы, вопросы, решения

кодировка сайта

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

1. Кодировка при работе без использования баз данных

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

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

Какое значение вкладывается в этот термин — "универсальная"? Это значит, что все составляющие создаваемого проекта, которые так или иначе касаются кодировок, должны иметь единую кодировку. Чтобы понять эту мысль разобьем сформулированный тезис на пункты, которые затем поэтапно разберем:

    1. Содержимое всех файлов должно иметь единую кодировку.

    2. Заголовки должны передавать единую кодировку.

    3. В качестве кодировки сервера необходимо установить единую кодировку.

    4. Кодировка соединения с БД также не должна отличаться от кодировки создаваемого проекта.

Это 4 основных правила, которые и являются составляющими сформулированного тезиса. Давайте теперь разберем каждый из этих пунктов.

Итак, на сервере создадим файл index.php, содержимое которого сохраним в кириллической кодировке. Сделать это можно, например, в редакторе Notepad++ через пункт меню Кодировки.

кодировка сайта

Узнать текущую кодировку файла можно взглянув в строку состояния редактора (в нижней панели).

кодировка сайта

Здесь уместно дать небольшой совет. При создании сайтов лучше пользоваться одной из двух кодировок: кириллической (windows-1251) или юникод без сигнатуры BOM (utf-8 without BOM). При этом следует знать, что юникод более универсален. Эта кодировка содержит большее количество символов, а потому идеально подойдет для мультиязычных сайтов, в то время как с кириллической кодировкой здесь могут возникнуть проблемы. Есть еще ряд нюансов при использовании юникода. В общем, лучше использовать ту кодировку, которая более универсальна, но если Ваш сайт содержит только кириллические символы, то никто не запрещает использовать Вам windows-1251, тем более, что она также имеет свои плюсы (детальнее об этом, возможно, в одном из следующих уроков).

Отлично, кодировка нашего файла кириллическая (windows-1251). У всех остальных файлов проекта, согласно первому пункту, кодировка должна быть аналогичной. В мета-тегах (между тегами head) также укажем эту кодировку:

<meta http-equiv="content-type" content="text/html; charset=windows-1251" />

Выведем какой-нибудь текст кириллицей на страницу:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251" />
<meta name="keywords" content="" />
<meta name="description" content="" />

<title>Кодировки</title>
<link href="" rel="stylesheet" type="text/css" />
</head>
<body>

<p>Тестовая строка</p>

</body>
</html>

Сохраним файл и попробуем открыть его в браузере… На экран выводится нечитабельная строка — набор вопросительных знаков вместо букв.

кодировка сайта

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

кодировка сайта

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

«Виноват» здесь не браузер, а сервер. Дело в том, что сервер отсылает в браузер так называемые заголовки, где указывается кодировка, в которой браузер должен отобразить содержимое файла. В качестве кодировки сервер берет кодировку по умолчанию, т.е. так называемую дефолтную кодировку сервера. Посмотреть дефолтную кодировку сервера можно в конфигурационном файле httpd.conf, расположенном на сервере в каталоге usr\local\apache\conf\. Здесь кодировка задается в строке AddDefaultCharset. Здесь же мы можем изменить кодировку на нужную нам, при этом не забывая после внесения изменений перезапускать сервер.

Но изменить кодировку получится только на локальном сервере. На сервере в сети хостер нам просто не даст доступ к конфигурационному файлу сервера… и правильно сделает :) Что же нам делать в таком случае? Неужели придется подстраиваться под настройки сервера? Конечно же нет. Для решения этой задачи существует 2 варианта, отвечающих за второй и третий сформулированные нами выше пункты.

Согласно второму пункту мы можем самостоятельно передать в заголовках необходимую кодировку. Делается это при помощи функции header(), в параметрах которой мы укажем тип документа и, собственно, кодировку. В самом верху файла (перед объявлением доктайпа (типа документа)) добавим строку кода:

<?php header("Content-type: text/html; Charset=windows-1251"); ?>

Если теперь обновить страницу в браузере, то увидим читабельный текст в кириллической кодировке. Замечательно — мы решили задачу! Путем передачи заголовков мы указали нужную нам кодировку. Но этот вариант не совсем универсален. Дело в том, что заголовки передаются посредством функции header(), т.е. для этого мы используем средства PHP. Но что же тогда делать, если файлы нашего проекта имеют расширение html? В файлах с таким расширением по умолчанию код PHP не выполняется, соответственно — заголовки не будут отправлены. Результат — вновь нечитабельный текст в браузере.

Альтернативой является второе решение (пункт 3), которое гораздо более универсальнее первого. Итак, согласно пункта 3 мы должны установить дефолтной кодировкой сервера нужную нам. Но как это можно сделать, если к конфигурационному файлу сервера мы доступа не имеем? Очень просто. Предусмотрен специальный файл, в котором можно изменять некоторые настройки сервера, в частности — дефолтную кодировку. Файл этот не имеет расширения и называется .htaccess (с точкой в начале имени файла). В самом файле достаточно прописать ту же строку, что и в конфигурационном файле сервера, но с указанием необходимой кодировки:

AddDefaultCharset windows-1251

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

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

кодировка сайта

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

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

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

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

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

<?php header("Content-type: text/html; Charset=utf-8"); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="keywords" content="" />
<meta name="description" content="" />

<title>Кодировка при работе с БД</title>
<link href="" rel="stylesheet" type="text/css" />
</head>
<body>



</body>
</html>

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

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

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

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

<p>Тестовая строка</p>

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

<?php 
	header("Content-type: text/html; Charset=utf-8"); 
	
	mysql_connect("localhost", "root", "") or die("Can't connect to server");
	mysql_query("SET NAMES 'utf8'") or die("Can't set charset");
	mysql_select_db("charset") or die("Can't select DB");
	
	$res = mysql_query("SELECT `text` FROM `test` WHERE `id`=". 1) or die(mysql_error());
	$row = mysql_fetch_assoc($res);
	
?>

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

<?php

	echo $row['text'];

?>

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

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

mysql_connect("localhost", "root", "") or die("Can't connect to server");
	mysql_query("SET NAMES 'utf8'") or die("Can't set charset");

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

Заключение

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

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

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

Автор: Кудлай Андрей

Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (57)

  1. Артур

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

  2. Иван

    Стоит сказать, что конструкция:

    AddDefaultCharset windows-1251

    срабатывает не на всех хостингах. Поэтому рекомендую использовать такую:

    CharsetDisable On

    AddDefaultCharset windows-1251
    php_value default_charset windows-1251

    Также стоило сказать про атрибут accept-charset для форм.

    Я как раз недавно тоже писал статью на эту тему на своем сайте. Не сочтите за СПАМ, но возможно кому-то будет интересно. Вот ссылка

    biznesguide.ru/other/136.html

    • Андрей Кудлай

      Спасибо за дополнение ;)
      Также немного дополню:
      — AddDefaultCharset — это директива Apache.
      — php_value default_charset — это директива PHP.
      Обе они отвечают за то, в какой кодировке будет отдаваться текст клиенту.
      О второй директиве я не упомянул по одной простой причине — на всех серверах, с которыми доводилось работать, я ее попросту не использовал, поскольку не возникало надобности. Ради интереса глянул в настройки локального сервера — эта директива закомментирована. Подозреваю, что у подавляющего большинства хостеров сделано также (ибо не вижу большого смысла указывать еще и кодировку в настройках PHP, если в настройках сервера она уже указана). Но, если все же проблемы возникнут, то об этой директиве стоит помнить.
      Кстати, могу ошибаться, но, скорее всего, правильно задавать кодировку здесь также, как и в случае с MySQL, т.е.:
      php_value default_charset «cp1251″

      • Шамшур Иван

        Да, опечатался. Правильно писать:
        php_value default_charset «cp1251″

        • matr

          а кавычки так и надо, а то я начинающий?
          «cp1251″
          или всеже они должны быть однородными?

          «cp1251″

          • Андрей Кудлай

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

    • Иван

      Админ, поставь на форму комментариев BB-code. А то реально вырезает спец.символы, и получается какой-то бред в комментариях

    • Николай

      Отличная работа. Спасибо.

  3. Игорь

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

  4. Светлана

    Спасибо за очень полезные советы!

  5. Дмитрий Денисов

    Спасибо. Да кракозябры они такие!!!

  6. Volond

    Спасибо, особенно за видео, т.к. в нём довольно подробно описаны все нюансы!

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

  7. Pocherk

    Если сайт делается в кодировке UTF-8, не повредит в файле .htaccess такая строчка:

    php_value default_charset utf-8

  8. Сергей

    Спасибо за интересный и полезный урок.

  9. Юрий

    информация полезная и необходимо видно будет применить

  10. Николай

    Очень нужная, полезная информация!

  11. Александр

    Спасибо за урок. Очень полезная информация для меня. Я бы хотел затронуть еще одну проблему с которой столкнулся и пока не могу решить. Я на локальный компьютер поставил не денвер описанный выше а XAMPP. Проблема заключается в том, что в панели phpmyadmin при просмотре содержимого таблицы отображаются кракозябры. При этом если данные в таблицу заносить через php скрипт то они на странице отображаются как надо. а в панели phpmyadmin кракозябрами. Если данные заносить через саму панель phpmyadmin то кракозябры и тут, и там. Это все относится к кириллическим символам. латиница отображается как надо. Везде установлена кодировка utf-8.
    Помогите, пожалуйста, разобраться с данной проблемой.

    • Андрей Кудлай

      К сожалению, с XAMPPом не работал. Проблема, скорее всего, в настройках MySQL. В конце урока показан файл с настройками MySQL, отвечающими в частности за кодировку. Найдите строку init-connect в конфигурационном файле и укажите нужную кодировку — она должна совпадать с кодировкой сервера. После этого не забудьте перезапустить сервер.

      • Александр

        Андрей, к сожалению я не смог найти файл my.cnf. Есть my.ini и там есть такие строки
        # C:/xampp/mysql/bin/my.cnf to set global options,
        # mysql-data-dir/my.cnf to set server-specific options (in this
        # installation this directory is C:/xampp/mysql/data) or
        # ~/.my.cnf to set user-specific options.
        По данным путям my.cnf я не обнаружил. (у меня отображаются все системные и скрытые файлы).
        где он в принципе может лежать?

        • Андрей Кудлай

          Файл my.cnf в Windows называется my.ini, т.е. это фактически аналоги друг друга, поэтому настройки mysql можно вполне изменять в файле my.ini

  12. Андрей Кудлай

    А в первой закомментированной строчке указан случайно не путь к этому файлу?
    # C:/xampp/mysql/bin/my.cnf
    А далее указано: to set global options, т.е. для установки глобальных настроек.

    • Александр

      C:/xampp/mysql/bin/my.cnf по данному пути этого файла нет. Средствами поиска виндоус файла с таким расширением в директории mysql нет. При ручном просмотре всех директорий я его также не обнаружил. Здесь одно из двух. Либо настройки производятся в другом файле, либо он замаскирован таким образом, что стандартными системными средствами отображения файлов его увидеть невозможно. Я решил эту проблему. Все оказалось достаточно просто. Всему виной моя невнимательность. При создании базы и таблицы в phpmyadmin для каждого поля создаваемой таблицы есть такой параметр как СРАВНЕНИЕ. Здесь обязательно нужно выставить кодировку UTF8_general_ci (ну это в моем случае, т.к. я все кодирую в utf-8). По умолчанию у меня почему то стояла кодировка utf8_icelandic_ci. После того как я во всех полях выставил значение UTF8_general_ci ну и конечно прописал заголовки и нужное кодирование базы в файле php описанное в Вашем уроке, все стало отображаться как надо. Хочу обратить внимание тех, кто будет использовать XAMPP хотя наверное и для Денвера это тоже справедливо, параметр сравнение можно установить только в момент создания таблицы. Потом отредактировать не удастся. По крайней мере я не нашел такого способа. И на последок хочу сказать, что у меня стоит Xampp 1.7.4, сейчас на официальном сайте разработчика доступна версия 1.7.7. Возможно там уде все по другому и таких проблем нет.

  13. Вячеслав

    Читаю вашу рассылку, много полезного узнаю. кстати у людей много проблем также возникает с кодировкой по данной причине — (не примите за спам) — kapon.com.ua/kod_v_denver.php

  14. ferdeshe@gmail.com

    как скачать урок, скорость маленькая онлайн смореть нет возможности

  15. ferdeshe@gmail.com

    спасибо!

  16. Анна

    Спасибо! Ломала себе голову как исправить этоу кодировку) с вашей помощью все решилось за 5 мин…

  17. Анатолий

    У меня проблема в том что я уже везде проставил
    utf-8 И вставил файл .htaccess в проект сайта.
    И при выводе в браузер результата то что в файлах прописано выводится хорошо а с денвера
    выходят непонятные символы. А когда удаляю файл
    .htaccess то все наоборот.

    Вот что написано в .htaccess

    AddDefaultCharset utf-8
    AddCharset utf-8 *

    CharsetSourceEnc utf-8
    CharsetDefault utf-8

    Помогите с проблемой…

    • Андрей Кудлай

      Для Денвера достаточно в файле .htaccess одной строки – AddDefaultCharset utf-8
      Файл должен находиться в корне сайта. Ну и соблюдайте все остальные правила: все файлы в той же кодировке, заголовки и т.д.
      Посмотрите в какой кодировке браузер показывает документ. Если показывает в кириллической, то значит файл .htaccess сервером просто игнорируется… значит где-то ошиблись с созданием этого файла (файл не в корне сайта, файл создан с расширением, внутри файла что-то не так). Внимательнее пересмотрите урок.

  18. Дмитрий

    Спасибо большое :) Теперь я разобрался. Всё понятно написано.

  19. Влад

    Спасибо. Верите или нет, но я только после этой статьи начал управлять кодировками. До этого они управляли мной и моими нервами. Очень полезно.

  20. Артем

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

    движок WordPress
    интернет магазин quick shop

  21. Артем

    Если кто сталкивался, подскажите как в форуме miniBB заменить кодировку на utf-8. там всё в — переменных, кодировки явно нет, а в исходном коде на всех страницах —

  22. Елена

    УРА! УРА! УРА! Вы помогли решить мою проблему!!!

  23. Svetlana

    1)в запросе MySQL из консоли из бд вместо кириллицы кокозябры достаются, когда ввожу SET NAMES utf8 (и другие пробовала ср866 как в курсе MySQL) одни кокозябры меняются другими.

    А когда вставляю кириллические данные из консоли они превращаются в ????????, а в бд вообще пусто.

    2)я нахожусь в турции, и хотела сделать сайт на турецком, столкнулась с проблемой кодировки, теперь вместо турецких символов выходит кириллические кокозябры. как узнать какая кодировка используется для других языков?

    • Svetlana

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

      Буду рада ответу

      • Андрей Кудлай

        О каких кириллический названиях идет речь? Уточните, пожалуйста, поскольку максимум, что можно скачать в этом уроке — это видео. Относительно консоли Денвера, то, полагаю, этот вопрос лучше задать на форуме официального сайта Денвера.

    • Андрей Кудлай

      Если Вы хотите сделать сайт на турецком языке, то нужно использовать кодировку UTF-8.

  24. Svetlana

    Вот так выглядит файл в каталоге:
    А вот так видео:

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

    • Андрей Кудлай

      К кодировке сайта это не имеет ни малейшего отношения. Дело в операционной системе, которой вы пользуетесь и которая не понимает кириллицу.

  25. Максим

    У меня кодировка не правильная в панели phpmyadmin где её менять?

    • Андрей Кудлай

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

  26. Наталья

    Большое спасибо за статью. Полно и доходчиво. Мучилась несколько дней с этими «краказябрами». Нутром чувствовала, что где-то проблема в кодировке, а где смотреть и как исправить не знала. Теперь все не своих местах,еще раз спасибо.

  27. alekslak

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near »test’ WHERE ‘id’=1′ at line 1

    Вот такое сообщение выдает после использования примера по БД, после того как подставляем

    Вроде уже 2016 год, все про гуглил, не пойму в чем дело???

    • Андрей Кудлай

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

  28. alekslak

    (подставляем — echo $row['text'];)

  29. Юрий

    Спасибо за содержательную статью, Андрей!
    Ко всему вышесказанному хотел бы добавить еще вот, что.
    Обычно, я пользуюсь текстовым редактором «Sublime text», а не «Notepade++».
    И заметил такую деталь: если отправлять кодировку в заголовке из самого файла, созданного в «Sublime text», то вылезают кракозябры. Но если создать аналогичный файл с помощью «Notepade++», то все выводится корректно.
    Можете прокомментировать данную ситуацию?

    • Андрей Кудлай

      Скорее всего ST сохраняет файл в другой кодировке. Просто выберите в какой кодировке необходимо сохранить файл. Сделать это можно в меню File — Save with Encoding

  30. LAPD

    Header функция помогла,только втыкать на каждую страницу пришлось.Спасибо.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree