Очевидно, что где-то внизу ваша строка интерпретируется как «ISO-8859-1», несмотря на то, что на самом деле это «UTF-8».
Вы можете проверить это с помощью следующего фрагмента кода в консоли irb или Rails:
s=[0x64,0xc3,0xa9].pack('c*') # => "d\xC3\xA9" ("dé" if UTF-8)
s.encoding # => #<Encoding:ASCII-8BIT>
s.encode "UTF-8", "UTF-8" # => "dé" ("de'")
s.encode "UTF-8", "ISO-8859-1" # => "dé" ("d~A(c)")
Я могу представить две возможности того, что пошло не так.
Дело 1
Ваш терминал, на котором запущена консоль Rails, либо не способен интерпретировать строку UTF-8, либо неправильно настроен.
Попробуйте следующий фрагмент кода (примечание, он может быть запущен любым пользователем, даже если перевод не определен):
s2 = I18n.t('programs.update.program_saved', :default => nil)
s2 ||= [0x64,0xc3,0xa9].pack('c*').encode("UTF-8", "UTF-8") # => "dé" ("de'")
p s2[-2,2].bytes # => [100, 195, 169] if the object is in UTF-8
# => [100, 233] if the object is in ISO-8859-1
и вы можете видеть, какова (внутренняя) кодировка объекта String.
Если это [100, 195, 169]
, то кодировка UTF-8, и, следовательно, и Ruby, и Rails правильно обрабатывают переведенный объект String как UTF-8, и поэтому проблема в вашем терминале. Ваш терминал неправильно интерпретирует байтовую строку [100, 195, 169]
, которую он получил от Rails, как ISO-8859-1 и выбирает символы и шрифт для отображения соответственно.
В Rails consolei на вашем терминале вы можете попробовать это; если терминал совместим с UTF-8, он должен правильно отображать символы:
[0x64,0xc3,0xa9].pack('c*').force_encoding('UTF-8')
# => "dé" ("de'") should be displayed.
Проверьте, что ваш терминал действительно способен отображать строки UTF-8 (большинство современных терминалов должны это делать, а старые - нет).
Также проверьте настройки вашего терминала. Этот ответ на вопрос «Как ввести символ Unicode в консоль Rails?» может помочь.
Дело 2
Именно Ruby интерпретирует входную строку как «ISO-8859-1» и внутренне преобразовывает ее в «UTF-8» (хотя это не должно происходить в настройках по умолчанию).
В этом случае, возможно, ваш файл yml может содержать некоторые символы, которые выглядят как «ISO-8859-1»; тогда Rails может интерпретировать весь файл как «ISO-8859-1» (хотя это очень маловероятно).
Вы можете проверить, действительно ли прочитанный вами файл (config/locales/fr.yml
) действительно в UTF-8, следующим образом:
fn = 'config/locales/fr.yml'
IO.binread(fn).force_encoding('UTF-8').valid_encoding? # => should be true
IO.binread(fn).force_encoding('ISO-8859-1').valid_encoding? # => false
К сожалению, есть небольшой недостаток. Некоторые символы UTF-8 могут быть законно интерпретированы как ISO-8859-1, и в таких случаях, как код (Rails) интерпретирует это, может отличаться. Если вы подозреваете, что это так, вы можете посмотреть на вывод вышеуказанной команды как IO.binread(fn).force_encoding('UTF-8')
и посмотреть, все ли символы соответствуют ожиданиям.
Если файл содержит символы не-UTF-8, исправьте это, и, надеюсь, все будет хорошо.
Или, в вашем конкретном случае, вы, возможно, можете исправить это как несуществующую работу, например
I18n.t('programs.update.program_saved').encode('UTF-8', 'ISO-8859-1')
Примечание
До тех пор, пока вы хотите настроить Rails как UTF-8 (настоятельно рекомендуется), убедитесь, что кодировкой вашего приложения по умолчанию является UTF-8. Проверьте это через
MyApp::Application.config.encoding # => #<Encoding:UTF-8>
(Ссылка: Настройка Rails-приложений )
Кроме того, если вы используете Heroku, установите кодировку по умолчанию на UTF-8. См. ответ на вопрос «Установите UTF-8 в качестве кодировки строки по умолчанию в Heroku» .
Обратите внимание, что было сделано серьезное обновление в 2018-11-05 для добавления случая 1.