Почему Rails 3 считает, что xE2x80x89 означает x80 x89 - PullRequest
1 голос
/ 07 июля 2011

У меня есть поле, скопированное со страницы utf-8:

"O’Reilly"

И сохранено в файле yml:

:name: "O\xE2\x80\x99Reilly"

(xE2x80x99 - это правильное представление UTF-8 этого апострофа )

Однако, когда я загружаю значение в хеш и выдаю его странице, помеченной как utf-8, я получаю:

OâReilly

Я посмотрел символ â, который кодируется в UTF-16 как x00E2, а символы x80 и x89 были невидимы, но присутствовали после â, когда я вставил строку. Я предполагаю, что это означает, что мое приложение выводит три символа UTF-16 вместо одного UTF-8.

Как заставить рельсы интерпретировать 3-байтовый код UTF-8 как один символ?

Ответы [ 3 ]

2 голосов
/ 09 июля 2011

В конечном итоге это было вызвано загрузкой файла syck (сгенерированного внешним скриптом) с psych (в rails).Загрузка с помощью syck решает проблему:

#in ruby environment
puts YAML::ENGINE.yamler => syck

#in rails
puts YAML::ENGINE.yamler => psych

#in webapp
YAML::ENGINE.yamler = 'syck'
a = YAML::load(file_saved_with_syck)
a[index][:name] => "O’Reilly"
YAML::ENGINE.yamler = 'psych'
2 голосов
/ 08 июля 2011

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

$ irb
>> "O\xE2\x80\x99Reilly"
=> "O\342\200\231Reilly"

Ваша строка представляет собой последовательность из 10 байтов, но 8 символов (как вы знаете). Самый безопасный способ убедиться, что вы выводите правильную строку в HTML (я полагаю, вам нужен HTML, поскольку вы упомянули Rails), - преобразовать непечатаемые символы в объекты HTML; в вашем случае до

O’Reilly

Это требует некоторой работы, но должно помочь в тех случаях, когда вы отправляете ваш HTML в UTF-8, но ваш конечный пользователь установил в своем браузере переопределение и показывает Latin-1 или какую-то другую глупую ограниченную кодировку.

1 голос
/ 08 июля 2011

Я предполагаю, что это означает, что мое приложение выводит три символа UTF-16 вместо одного UTF-8.

Это на самом деле не UTF-16, который редко используется в Интернете (и во многом там ломается).Ваше приложение выводит три символа Unicode (включая два невидимых управляющих кода), но это не то же самое, что кодировка UTF-16.

Возможно, проблема в том, что YAMLфайл читается так, как если бы он был в кодировке ISO-8859-1, так что байт \xE2 отображается на символ U + 00E2 и так далее.Я предполагаю, что вы используете Ruby 1.9, а YAML анализируется в байтовые строки с соответствующей кодировкой ASCII-8BIT вместо UTF-8, что приводит к тому, что строки подвергаются циклу транскодирования (искажения) позже.в этом случае вам, возможно, придется force_encoding считать строки обратно тем, какими они должны были быть, или установить default_internal, чтобы строки считывались обратно в UTF-8.Беспорядок это.

...