«Правильная» 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 следующий тег:
    <meta http-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. То есть в данном случае запись идет БЕЗ дефиса, что вносит ещё больший когнитивный диссонанс в понимание происходящего…
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 72
    • +34
      Так вот оно что) Оказывается не во всех грехах виноват IE)
      • НЛО прилетело и опубликовало эту надпись здесь
        • +47
          Лояльность в отношении трактовки стандартов ни к чему хорошему, как правило, не приводит ;)
          • +4
            Да? Т.е. надо сразу после встретившейся ошибки упасть на бок или выдать грозное сообщение, которое простому пользователю ни о чем не говорит? Есть известные распространенные ошибки, и хороший браузер должен как можно более прозрачно для пользователя постараться их исправить. Да, в какой-то мере это способствует распространению этих ошибок. Но с другой стороны пользователь не имеет возможности повлиять на содержимое/настройки посещаемого сайта/сервера. А посему лично я бы предпочел тот браузер, который корректно отобразит наибольшее количество страниц, несмотря на ошибки в них.
            • +2
              Кстати, разработчики стандартов сами ошибки допускают, которые потом вынужденно копируются теми, кто по этому стандарту работает. Яркий тому пример поле referer при том, что правильно было бы referrer.
              • +22
                Раньше IE много ругали за то, что он слишком мягко относится к стандартам, сейчас ругают за то, что следует им. Не угодишь.
                • +3
                  то что он совсем не следует одним стандартам не противоречит тому, что он слишком строго следит за другими :)
                  • –2
                    Я ИЕ в данном случае не ругаю, что вы. Я говорю, что из двух браузеров я выберу тот, который лучше отобразит ошибочные страницы.
                    • +3
                      IE ровно поэтому и мягко относился к стандартам. Но сейчас важно им следовать. Слишком быстро веб прошлого превратился в ад из-за такого отношения.
                      • –2
                        Ответьте на простой вопрос: что лучше — выдать ошибку, с которой посетитель сайта ничего не может поделать, т.к. не контролирует посещаемый ресурс, или попытаться отобразить по какой-то определенной логике?

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

                        Я вам приведу такой пример отвлеченный, чтобы легче было ответить: попадается вам битый архив (или упакованный с нарушением стандарта). Какая реализация архиватора будет лучше: та, которая попытается распаковать архив или та, которая выдаст кучу матюков и пошлет пользователя куда подальше?
                        • +4
                          Отвечаю: лучше следовать стандарту.

                          Вспомните как раньше IE пытался ориентироваться не на mime type, а на содержимое. Ничего хорошего из этого не вышло. Туда же можно отнести уязвимость с UTF-7.
                          • 0
                            Мне думается, что плохую имплементацию и нарушение стандартов нельзя складывать в одну кучу с расширением стандартов. Не знаю, как еще эту мысль можно донести. Но ваше право предпочитать негибкое ПО :)
                          • +1
                            Лучше выдать ошибку, это поможет правильно настроить сервер (указать правильную кодировку в конфиге).
                            • 0
                              Как это поможет _посетителю_?
                              • 0
                                Это поможет администратору сервера обнаружить ошибку, а не списывать всё на глюки браузера.
                                • 0
                                  _Посетитель_ придет на сайт, разработанный по жестким стандартам и отлаженный на этапе разработки.
                                  Я не имею в виду, что разработчикам ИЕ прямо сейчас надо «дергать рубильник», отключающий самостоятельность поведения. Этот рубильник не надо было трогать еще тогда, в самом начале своего пути.
                                  • 0
                                    И где бы тогда был Microsoft.

                                    Вообще история веба началась с самовольного впиливания в HTML не включенного в стандарт тега IMG… Правда мелкософт тут не причем.

                                    Другая древняя история с полями в див, когда Microsoft сделали отображение % в дивах как логично, а не как написано. Что весьма доставляло дизайнерам в 6ом эксполрере. А в итоге с 7 эксплорером, где микрософтовцы извинились, покаялись и «сделали всё обратно» куча резинового дизайна «поехало».
                                  • +1
                                    до посетителя такая ошибка попросу не дойдёт ибо будет замечена гораздо раньше выкладки на продакшен.
                                    • 0
                                      Посетитель, ошибки не увидит, её раньше заметит веб-разработчик, погуглит, найдет эту статью и сообщит администратору сервера, что у него не все в порядке с настройками.
                                  • +1
                                    Странно, почему программеры на сях, яве и т.д. никогда не парились на тему ошибок из-за собственной криворукости. Есть ошибка — надо править. Задолбали, право слово.
                                  • –2
                                    И еще, ИЕ не мягко относился к стандартам, он их прямо нарушал, отсюда ад. А вот добавление еще одного нестандартного алиаса к кодировке ничего плохого не несет в себе. Все браузеры имеют собственные расширения стандартов, и это нормально. Считайте utf8 — проприетарным расширением стандарта. Да, ие не обязан ему следовать, но раз ошибка распространена, то, учитывая это, можно сделать программу более дружественной по отношению к пользователю, который сможет-таки увидеть нужный ему контент.
                                    • +2
                                      И еще, ИЕ не мягко относился к стандартам, он их прямо нарушал, отсюда ад. А вот добавление еще одного нестандартного алиаса к кодировке ничего плохого не несет в себе.
                                      Конечно, и определение содержимого не по mime type — тоже ничего плохого, правда? Зато пользователю покажем всё как надо.
                                      • 0
                                        Вопрос лишь в нарушении стандартов. Если оно есть, значит это плохо. Если нарушения нет, то зависит от надежности алгоритма и качества имплементации. Если сделано качественно, то это только плюс софту.
                                        • 0
                                          Отдельно хочу написать слово минусаторам: посетите на досуге вот этот урл: validator.w3.org/check?uri=http%3A%2F%2Fhabrahabr.ru%2Fblogs%2Fwebdev%2F130511%2F&charset=%28detect+automatically%29&doctype=Inline&group=0 (теги у меня не пролезают на хабр, поэтому таким образом размещаю).

                                          Прикиньте, если бы браузер начал брыкаться, метериться и отказался бы в итоге загрузить хабрахабр? Вы бы выкинули его и поставили другой, который был бы не таким капризным к ошибкам, или перестали бы посещать Хабр?
                                          • +3
                                            Хабрапрограммеры исправили бы.
                                            • 0
                                              Да это не важно, я не об этом. На хабре куча несоответствий XHTML 1.0 Transitional, но браузеры именно благодаря терпимости к ошибкам отображают сайт без проблем, и почему-то никто не возмущается таким их поведением. А вот поддержка utf8 (вместо utf-8) почему-то определена оппонентами как «зло». Двойные стандарты? :)
                            • 0
                              Но ни что не мешает браузеру сообщать об ошибках на странице человеческим языком.
                        • +5
                          IE в данном случае как раз действует ровно в соответствии со стандартными названиями кодировок (http://www.iana.org/assignments/character-sets). См. также статью IE9 Compatibility: Proper Use of the Charset Token от Eric Lawrense
                          • +24
                            wtf8
                          • –3
                            Удивительно.
                            У меня есть сервера которые устанавливались еще в далеком 2008 году. Где кодировка выставлено верно, а именно URF-8.

                            Хотелось бы узнать в каких дистрибутивах автор нашел подобное неверное обозначение кодировки.
                            • +29
                              > верно, а именно URF-8.
                              действительно, не подкопаться.
                              • –11
                                Объясните, это шутка юмора такая?
                                Я уже начал думать, что у меня сильные пробелы в знаниях, Гугл уверено предлагает поискать про UTF-8.
                                • 0
                                  Ну да, это типа ирония была.
                                  Из контекста же понятно.
                                • 0
                                  Дайте пожалуйста ссылку на URF-8 — я совершенно серьёзно не смог найти, запрос предлагают сменить на UTF-8 и всё.
                                • +1
                                  В смысле «в каких дистрибутивах»? Речь идет о дистрибутивах Linux? они-то тут причем?
                                  Данное поведение имеет место независимо от дистрибутива, и зависит от того, какие настройки прописаны в виртуальных хостах.

                                  • 0
                                    Именно. Только если вы возьмете исходники апача вы там уведите верное определение кодировки.
                                    А это означает, что появление НЕВЕРНОГО описания кодировки на совести того кто собирал дистрибутив (из которого взят был пакет), или конфигурировал сам апач в ручную, изменив значение по умолчанию с верного на неверное.
                                    • 0
                                      Проблема не в исходниках того или иного веб-сервера, тут исходники вообще не причем. Да и nginx и apache отрабатывают верно — к ним претензий нет. Проблема в том, что люди зачастую в настройках виртуальных хостов сами вручную указывают неверную кодировку, даже не подозревая об этом (просто скопировав откуда-нибудь из примеров, коих бесчисленное множество в интернете, и в последствии при разработке возникают нетривильные ошибки
                                      • –4
                                        Простите еще раз. Когда Вы что то ставите из исходников, к ним в обязательном порядке идет и конфиг. Чтобы сделать сейчас неправильно — нужно залезть и исправить с правильного на неправильное.

                                        Вот мне и стало интересно, где кто сто столкнулся с этой абсурдной ситуацией.

                                        • 0
                                          то есть у вы пользуетесь только дефолтными конфигами?
                                          абсолютно не могу такое представить в отношении веб-серверов :)
                                          • 0
                                            Все очень просто: Эникейщик взял, скопипастил, а в конфиги даже не смотрел.
                                            • 0
                                              Ненене… кажется, вы неправильно понимаете. Конфиг компиляции — это одно, а конфиг виртуального хоста — это другое. После того как веб-сервер скомпилялся, надо же настроить на какую директорию он будет смотреть, какой хост (домен) цеплять и т.п. И именно за это и отвечает конфиг виртуального хоста. А кодировка по-умолчанию, насколько мне известно, вообще не прописывается даже в тестовых виртуальных хостах.
                                              • 0
                                                А вот вам статистика. Я собирал материалы для доклада и пробежал спайдером по 200 тыс. сайтов в рунете. Помимо нужных мне данных собрал и кодировки из заголовков.

                                                И вот, при правильном написании windows-1251 и UTF-8 мне встретились:

                                                win-1251
                                                windows1251
                                                windows_1251
                                                x-cp1251
                                                windows-cp1251
                                                unicode
                                                utf8
                                                UTF
                                                

                                                Более редкие случаи связаны с неправильным аргументом в функции, формирующие заголовок Content-type:

                                                =utf-8
                                                cp-1251>charset=windows-1251
                                                

                                                Особо ушлый товарищ выдал такое:

                                                koi8-r/windows-1251
                                                

                                                Мол, выбирайте по вкусу.

                                                Короче, итог такой: из всей выборки 2.43% сайтов неправильно отдают charset. Конкретно по utf8 — 0.27% из всех вариантов написания кодировки UTF-8.
                                        • 0
                                          Зачастую, многие разработчики, при конфигурации виртуальных хостов копируют настройки откуда-нибудь из интернета или же из других мест. И при этом в их настройки «перекочевывает» ошибка.

                                          Вы не внимательно читаете.
                                        • 0
                                          IE также не понимает cp1251 прописанным в htaccess. Как раз на днях столкнулся с этим, вообще никак не хотело реагировать на jQuery, изменил на windows-1251 и все проблемы исчезли
                                          • +3
                                            1) Масштабные ошибки в документации встречаются сплошь и рядом. Скажем, вспоминается, что не только в документации (точнее FAQ) nginx, но даже в дефолтном (который идет в комплекте с системой!!!) htaccess, который поставляется в комплекте Drupal — дается некорректный конфиг для SEO-урлов, из-за которого без корректировки не будут работать мультиязычные сайты. Ошибка черте сколько времени кочует туда-обратно…

                                            2) Не надо приставать особо к IE. Он стал жертвой обстоятельств. :-) Впору вообще писать топик про ошибки Файрфокса, некоторые из которых существуют годами и хрен бы кто их исправил… Скажем, попробуйте абсолютно отпозиционировать элемент внутри fieldset с position:relative. Все браузеры, включая IE6, не имеют с этим никаких проблем, а вот FF косячит. Вот буквально на днях вроде наконец поправили и в FF10 все станет нормально… Но, блин, IE6, которому больше 10 лет этого косяка не имеет!
                                            • 0
                                              >1. Drupal. Здесь суть не в том что ошибка обнаружена, а в том был ли запостен багфикс в багтрекер или нет. Может просто разработчики незнают о нем потому как не пользуются мультиязычными сайтами (ну чисто теоретически). И надо им в этом помочь
                                            • 0
                                              IE6 на Windows XP Pro & SP2 тут ни каких кракозябр не показывает (хотя IE ох как любит ставить по дефолту windows-1251). Скажите, дохтур, что я делаю не так?
                                              • 0
                                                эм… вот только что проверил на своей виртуалке в IE6 (который ставится по дефолту в WinXP). Бага воспроизводится: bit.ly/r6nWRe. Ну и вот тут можно проверить: ipinfo.info/netrenderer/ через online-эмуляцию IE.
                                                • 0
                                                  Виртуалки это конечно неплохо, но у меня нативная установка и бага в ней нет. Что лично мне позволяет усомниться в наличие оного. Нам нужен еще один пользователь без виртуалок который может зайти на урл.
                                                  • 0
                                                    Так, проверили на Windows 7 с IE 9.0.8112 и так крокозябры таки да, имеются. Я же на своем 6.0.2900.2180.xpsp_sp2_rtm ни чего подобного не наблюдаю. Учитывая, что это не дефольтный у меня браузер, а чисто для тестов, то и настроек в нем ни когда не подкручивал.
                                                    • +1
                                                      странная ситуация :) быть может в SP2 идут какие-то неофициальные фиксы 6ого ишака?
                                                      • 0
                                                        Тут даже не знаю, это интегрированный SP2 он шел при инсталяции ОСи изначально. В общем нужно пособирать статистику с других IE по возможности, хотя думается SP2 в наше время уже не откопать.
                                                • +3
                                                  Кстати, добавлю пару замечаний. Во-первых, писать header(Content-Type) в PHP — это быдлокод, надо просто в конфиг PHP вписать default_mimetype и default_charset. Во-вторых, несмотря на то, что кодировка называется utf-8, при работе с MySQL, ее надо писать (в конфиге и в переменных типа SET NAMES) в виде utf8 — как не странно.

                                                  А разработчики ИЕ все делают в этот раз правильно.
                                                  • 0
                                                    Про header(Content-Type) согласен, но в контексте данной статьи это имелось ввиду в качестве примера, в том плане, что кодировку можно выставлять не через web-сервер а посредством самого интерпритатора.
                                                    Про MySQL опять же согласшусь, и надо сказать это вносит ещё большую путанницу o_O
                                                  • +10
                                                    StraNNikk, дай тебя расцелую!!!
                                                    Блин, я всю голову сломал с одним проектом, который у меня напрочь отказывался аяксовые запросы делать в IE хрен знает сколько времени убил на то, чтобы найти ошибку.
                                                    А тут бац, зашел на хабр, тут статья. Поставил дефис, все заработало! Ну это ппц вообще, я в шоке. :) Еще раз спасибо, жаль кармы нет тебе плюсиков наставить((((
                                                    • +3
                                                      всегда пожалуйста! ;-) а про плюсики… никакие плюсики не заменят ощущение того, что статья принесла кому-то реальную пользую! ;-)
                                                      • 0
                                                        И от меня спасибо тоже, правда появись эта статья на 3 дня раньше цены б ей небыло. а то какраз эта ошибка вывкакивала, но нарыл уже в других местах.
                                                        Еще по дури вылазила у меня ошибка с ajax.response (Firefox, Chrome — нормально работали ) а вот ИЕ в обязательном порядке требовал responseText.
                                                        И еще Firefox Chrome нормально отрабатывают такой код:
                                                        tbl = document.createElement('table')
                                                        tbl.innerHTML = ''

                                                        А ИЕ в этом случае выдает ошибку так как наверное хочет чтоб ему делали таблицу в DOM-е а не на чистом HTML
                                                      • 0
                                                        К слову у меня вот это использовалось jqueryui.com/demos/tabs/ и я долго не мог понять почему пример взятый с сайта работает в IE, а после того как я перенес к себе в проект не работает. Оказалось в одном модуле, который вообще не я писал (шаблонизатора) стояло как раз utf8 и никого не трогало, не где не проявлялось, пока я не решил добавить ajax формочек. Вот там-то и всплыл этот баг с IE, при чем ошибка выдавалась стандартная аяксовая, по типу «не могу загрузить и все тут». А из миллиона причин та что с utf8 я бы наверное проверил последней.
                                                      • 0
                                                        Разница между utf-8 и utf8, кстати, не только в контексте браузеров присутствует. В моём любимом языке программирования Perl между ними вообще коренные различия, хотя кто бы ожидал такого от лишнего тире…
                                                        • +1
                                                          Не тире — дефисоминуса.
                                                          • 0
                                                            Дефис и минус тоже сильно отличаются.
                                                            • 0
                                                              В общем дефис это.
                                                              • 0
                                                                Да, конечно; но тут-то речь не о дефисе (x2010) и не о минусе (x2212), и тем более не о тире (x2014), а о простом дефисоминусе, который у нас на клавиатурах (x002D).
                                                          • 0
                                                            Или же использовать в HTML следующий тег:
                                                            <meta http-equiv="content-type" content="text/html; charset=utf-8" />

                                                            А я-то думал браузеры-то на него давно забили и кодировку выставляют исключительно (кроме случаев ручного выбора) как раз согласно тому, что сообщил сервер в header-е http-ответа. Неужели нет?
                                                            • –1
                                                              ммм… нет. а почему браузеры должны были на него забивать? как раз этот тег позволяет «рулить» кодировками независимо от того, что ответил сервер в заголовках. А если говорить точнее, то значения данного тега имеют наивысший приоритет при выборе заголовков ответа от сервера.
                                                              • +1
                                                                значения данного тега имеют наивысший приоритет

                                                                Что-то не замечал, вроде на практике получалось наоборот. Спасибо, полезно знать. Поэкспериментирую.
                                                                • +1
                                                                  Наивысший приоритет имеет заголовок СЕРВЕРА. На HTML тег браузер смотрит только если сервер ничего ему не выдает.
                                                                  • –1
                                                                    да, точняк — с наивысшим приоритетом я перегнул палку. Значение HTTP-заголовка превалирует над значением META-тегов только в случае, когда заголовок не понятен или же при ненормальном статус коде (!=200) и не у всех заголовков.
                                                            • +3
                                                              Забавно, порылся поиском по содержимому своего сервера, нашёл «utf8» в PHP скриптах WordPress
                                                              wp-config-sample.php
                                                              /** Кодировка базы данных для создания таблиц. */
                                                              define('DB_CHARSET', 'utf8');

                                                              Вот может откуда ноги у ошибок растут, браузерам надо одно написание, а БД другое.
                                                              • 0
                                                                Автор, добавьте, что в MySQL запросах нужно писать utf8, а то щас ломанутся все исправлять свой «set names utf8» на «set names utf-8»

                                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.