Я не так давно обновил один из проектов до Rails 4.2 и заметил интересный эффект: кодировка обработанных html файлов в ассетах меняется на ISO-8859-1.
Данная проблема актуальна для Sprockets 3.0.0 и 3.0.1.
Проблема нашлась в EncodingUtils#detect_html:
При загрузке файла Sprockets пытается определить стандарт юникода, почистить строку от BOM и вернуть в нужной кодировке. В случае с html, если не удалось определить кодировку на этом этапе, то пытаемся дать это сделать charlock_holmes (если он установлен), иначе принудительно конвертируем в ISO-8859-1.
Проблема в том, что BOM не является обязательным для UTF-8 и поэтому практически все редакторы сохраняют файлы в UTF-8 без BOM. А это значит, что метод `detect_unicode_bom` по большому счету является бесполезным и html файлы в ассетах всегда будут преобразованы в ISO-8859-1.
Решить проблему можно следующими способами:
1. Переопределить Mime Type для text/html в инициализаторе:
2. Установить charlock_holmes.
3. Обновиться до версии 3.0.2, где поведение по умолчанию изменено с ISO-8859-1 на Encoding.default_external (pull request)
Данная проблема актуальна для Sprockets 3.0.0 и 3.0.1.
Проблема нашлась в EncodingUtils#detect_html:
#...
module Sprockets
# Internal: HTTP transport encoding and charset detecting related functions.
# Mixed into Environment.
module EncodingUtils
extend self
#...
# Public: Detect charset from HTML document. Defaults to ISO-8859-1.
#
# str - String.
#
# Returns a encoded String.
def detect_html(str)
str = detect_unicode_bom(str)
# Attempt Charlock detection
if str.encoding == Encoding::BINARY
charlock_detect(str)
end
# Fallback to ISO-8859-1
if str.encoding == Encoding::BINARY
str.force_encoding(Encoding::ISO_8859_1)
end
str
end
CHARSET_DETECT[:html] = method(:detect_html)
end
end
При загрузке файла Sprockets пытается определить стандарт юникода, почистить строку от BOM и вернуть в нужной кодировке. В случае с html, если не удалось определить кодировку на этом этапе, то пытаемся дать это сделать charlock_holmes (если он установлен), иначе принудительно конвертируем в ISO-8859-1.
Проблема в том, что BOM не является обязательным для UTF-8 и поэтому практически все редакторы сохраняют файлы в UTF-8 без BOM. А это значит, что метод `detect_unicode_bom` по большому счету является бесполезным и html файлы в ассетах всегда будут преобразованы в ISO-8859-1.
Решить проблему можно следующими способами:
1. Переопределить Mime Type для text/html в инициализаторе:
Rails.application.assets.register_mime_type('text/html', extensions: '.html', charset: :default)
2. Установить charlock_holmes.
3. Обновиться до версии 3.0.2, где поведение по умолчанию изменено с ISO-8859-1 на Encoding.default_external (pull request)
lolmaus
Спасибо, конечно, плюсанул, но стоило ли это поста на Хабр? По формату больше подходит для StackOverflow или какого-нибудь Rails-форума. Тем более что проблема решается, как я понял из ваших слов, одной командой
bundle update sprockets
.llxff Автор
Когда я столкнулся с этой проблемой, то нагуглить ничего не получилось и решение нашлось не быстро. Поэтому решил запостить, мало ли кто столкнется с этой проблемой еще. Плюс 3.0.2 появилась только вчера.
Dreyk
о, спасибо. Настало время обновить бандл)