Замена time_ago_in_words плагином jQuery timeago в i18n-приложении Rails 3.2

Запустив готовое приложение Rails Tutorial с помощью Рекомендации по использованию Rails, я получил предупреждение не использовать метод time_ago_in_words, так как "вычислять время на стороне сервера слишком дорого", поэтому они предоставляют пример кода чтобы изменить свою реализацию, чтобы использовать плагин timeago jQuery. Звучало так, как будто это внесет интересное изменение, поэтому я попытался это сделать. Мой оригинальный код, который использовал time_ago_in_words, находится в двух местах:

app/views/shared/_feed_item.html.haml

# ...
%span.timestamp
  = t('.time_posted_ago', time: time_ago_in_words(feed_item.created_at) )

app/views/microposts/_micropost.html.haml

# ...
%span.timestamp
  = t('.time_posted_ago', time: time_ago_in_words(micropost.created_at))

Я изменил код для использования timeago следующим образом, используя тег HTML5 time:

app/views/shared/_feed_item.html.haml

# ...
%time.timeago{ datetime: feed_item.created_at.getutc.iso8601 }
  = t('.time_posted_ago', time: feed_item.created_at.to_s)

app/views/microposts/_micropost.html.haml

# ...
%time.timeago{ datetime: micropost.created_at.getutc.iso8601 }
  = t('.time_posted_ago', time: micropost.created_at.to_s)

Что, как я думал, оставило меня только для добавления метода timeago() в мой файл coffeescript:

приложение/активы/javascripts/application.js.coffee

$(document).ready ->
  $("time.timeago").timeago()

Это не сработало, поэтому я попытался переместить оператор в microposts.js.coffee и users.js.coffee с $(document).ready -> и без него, и все равно не получилось. Затем я подумал, что, возможно, необходимые библиотеки для timeago не включены по умолчанию в jquery-rails, поэтому я добавил их:

приложение/активы/javascripts/application.js.coffee

//= require jquery
//= require jquery_ujs
//= require jquery.min
//= require jquery.timeago
//= require bootstrap
//= require_tree .

Добавление здесь объявлений jquery.min.js и jquery.timeago.js не сработало, и я также предполагаю, что мой синтаксис отключен, поскольку они сломали другие элементы моей страницы, которые полагаются на javascript.

Итак, насколько я понимаю, я думаю, что у меня правильный код реализации в моих файлах haml, но я просто не знаю:

  1. в какой файл coffeescript я должен поместить вызов $("time.timeago").timeago() и как я должен его написать, если то, что у меня есть, неверно
  2. включены ли библиотеки timeago в rails-jquery
  3. если нет, то как их правильно включить

Потратив на это много времени, я все же попробовал гем rails-timeago, который, а также наличие нескольких хороших помощников, действительно работал над тем, чтобы время отображалось правильно. Тем не менее, похоже, это не очень хорошо работает с реализацией метода rails t() выше, чтобы просто получить время в словах, а затем интерполировать его в строку i18n.

Итак, как я могу получить желаемый эффект time_ago_in_words с помощью плагина timeago JQuery в приложении Rails 3.2 с i18n?


person Paul Fioravanti    schedule 20.06.2012    source источник


Ответы (1)


Мне удалось собрать решение с помощью гема rails-timeago. Это не оптимально, но, похоже, дает желаемый эффект времени назад, что довольно приятно. Я хотел бы знать, как получить такой же эффект в Rails, используя только плагин timeago jQuery и теги %time.timeago. В любом случае, надеюсь, кому-то это будет интересно.

Настраивать

Gemfile

gem 'rails-timeago', '1.3.0'

config/initializers/timeago.rb

Rails::Timeago.default_options limit: proc { 20.days.ago }, nojs: true
Rails::Timeago.locales = [:en, :it, :ja]

Создайте каталог app/assets/javascripts/locales, чтобы внести изменения в строки timeago i18n. Для полноты картины я взял три локали, которые мне нужны для моего приложения, из репозитория jQuery-timeago Github и поместил их в каталог, но фактически изменил только файл локали ja.

приложение/активы/javascripts/application.js.coffee

# ...
//= require jquery
//= require jquery_ujs
//= require rails-timeago

приложение/представления/макеты/application.html.haml

# ...
%head
  # ...
  = javascript_include_tag "application"
  = timeago_script_tag

Реализация

app/views/microposts/_micropost.html.haml

# ...
%span.timestamp
  = t('.time_posted_prefix')
  %time<
    = timeago_tag(micropost.created_at)
    = t('.time_posted_suffix')

Код для app/views/shared/_feed_item.html.haml такой же: просто замените micropost на feed_item.

i18n

config/locales/en.yml

microposts:
  micropost:
    time_posted_prefix: Posted
    time_posted_suffix: ""

config/locales/it.yml

microposts:
  micropost:
    time_posted_prefix: Pubblicato
    time_posted_suffix: ""

config/locales/ja.yml

microposts:
  micropost:
    time_posted_prefix: ""
    time_posted_suffix: に投稿された。

Строки для shared.feed_item в файлах i18n одинаковы.

Я не смог найти способ динамического использования t() с результатом timeago_tag (например, t('.time_posted_ago', time: timeago_tag(micropost.created_at))), поэтому я поместил результат между префиксом и суффиксом. timeago предоставляет префиксы/суффиксы, связанные со временем, но не связанные с "публикацией", поэтому они были добавлены выше.
Чтобы избавиться от пробела между выводом timeago_tag и time_posted_suffix (специально для японского языка), я обернул эти два тега в теге %time< с < для
удалить все пробелы в теге. Это небольшая вещь, но меня это раздражало, поэтому я хотел добавить ее, но это ни в коем случае не обязательно, если вы не используете языки, которым нужно значение в ключе time_posted_suffix. Я также предполагаю, что есть лучший способ сделать это.

Проблемы

Изначально у меня были jquery.timeago.en.js, jquery.timeago.it.js и jquery.timeago.ja.js под app/assets/javascripts/locales, но у меня возникла проблема, из-за которой файл en не загружался для локали en; вместо этого последний файл в алфавитном порядке в каталоге, которым был ja, будет использоваться с локалью en. Итак, я переименовал файл en в jquery.timeago.xx.js, чтобы отображался английский язык. Я попытался переместить файл en за пределы каталога локалей, но он так и не был выбран, поэтому он стал xx.

Обновлять

Проблемы с i18n, которые у меня были, теперь решены. Подробности см. в этой проблеме Github. Подводя итог, я избавился от своего каталога app/assets/javascripts/locales и поместил только jquery.timeago.ja.js, единственный файл, который я действительно хотел настроить, в каталоге lib/assets/javascripts/locales, что означает, что для локалей :it и :en используются переводы по умолчанию timeago, а переводы :en отображаются должным образом. Итак, я получил то, что считаю хорошим решением этой проблемы с драгоценным камнем rails-timeago.

Обновление 2

Это решение в настоящее время работает локально, но неправильно развертывается в Heroku из-за проблем с предварительной компиляцией ресурсов...

Обновление 3

Нашел конфигурационное решение, которое работает локально и с Heroku:

config/initializers/timeago.rb

Rails::Timeago.default_options limit: proc { 20.days.ago }, nojs: true
Rails::Timeago.locales = [:en, :it, :ja]
Rails::Timeago.map_locale "en", "jquery.timeago.js"  # default
Rails::Timeago.map_locale "it", "locales/jquery.timeago.it.js"  # default
Rails::Timeago.map_locale "ja", "timeago/jquery.timeago.ja.js"  # customized

config/environments/production.rb

# ...
config.assets.precompile += %w( jquery.timeago.js locales/jquery.timeago.it.js timeago/jquery.timeago.ja.js )

И в этом случае единственный необходимый пользовательский файл — это app/assets/javascripts/timeago/jquery.timeago.ja.js.

Дополнительную информацию можно найти в связанной с Github проблеме.

person Paul Fioravanti    schedule 21.06.2012