Replacing time_ago_in_words with the timeago jQuery plugin in i18n-ized Rails 3.2

Running my finished Rails Tutorial application through Rails Best Practices gave me a warning not to use the time_ago_in_words method as "too expensive to calculate server-side time," so they provide some sample code to change your implementation to use the timeago jQuery plugin . It seems like this would make interesting changes, so I tried to do it. My source code that used time_ago_in_words is in two places:

app / views / general / _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)) 

I changed the code to use timeago as follows using the HTML5 time tag:

app / views / general / _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) 

Which, I thought, only left me to add the timeago () method to my coffeescript file:

application / assets / javascripts / application.js.coffee

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

This did not work, so I tried to move the microposts.js.coffee and users.js.coffee statement with and without $(document).ready -> and still not. Then I thought that maybe the required libraries for timeago are not included by default in jquery-rails , so I added them:

application / assets / javascripts / application.js.coffee

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

Adding jquery.min.js and jquery.timeago.js did not help here, and I also assume that my syntax is turned off, as they overloaded my other page elements that rely on javascript.

So, as far as I understand, I think I have implementation code in my haml files, but I just don't know:

  • in which coffeescript file should I put a call to $("time.timeago").timeago() and how to write it if I have the wrong
  • are timeago libraries timeago in rails-jquery
  • if this is not the case, how to enable them.

After spending a lot of time on this, I ended up trying out the rails-timeago stone , which, along with some good helpers, worked to make the time display correctly. However, this doesn't seem to work so well with the implementation of the rails t() method above, just to get the time in words and then interpolate it into the i18n string.

So, how can I get the desired time_ago_in_words effect using the Timeago jQuery plugin in a Rails 3.2 application with i18n?

+4
source share
1 answer

I managed to crack the solution using rails-timeago gem . This is not optimal, but it seems to get the desired taimago effect, which is pretty nice. I would like to know how to get the same effect in Rails using only the timeago jQuery plugin and the %time.timeago tags. In any case, I hope this is interesting to someone.

Customization

Gemfile

 gem 'rails-timeago', '1.3.0' 

configurations / initializers / timeago.rb

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

Create the app / assets / javascripts / locales directory to put the settings in the timego i18n lines. For completeness, I took the three locales I wanted for my application from the jQuery-timeago Github repository and put them in a directory, but actually changed the ja local file.

application / assets / javascripts / application.js.coffee

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

application / views / layouts / application.html.haml

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

Implementation

app / views / microposts / _micropost.html.haml

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

The code for app / views / shared / _feed_item.html.haml is the same: just replace micropost with feed_item .

i18n

<strong> Config / locale / en.yml

 microposts: micropost: time_posted_prefix: Posted time_posted_suffix: "" 

<strong> Config / locale / it.yml

 microposts: micropost: time_posted_prefix: Pubblicato time_posted_suffix: "" 

<strong> Config / locales / ja.yml

 microposts: micropost: time_posted_prefix: "" time_posted_suffix: γ«ζŠ•η¨Ώγ•γ‚ŒγŸγ€‚ 

The lines for shared.feed_item in the i18n files are the same.

I could not find a way to use t() dynamically with the result of timeago_tag (e.g. t('.time_posted_ago', time: timeago_tag(micropost.created_at)) ), so I put the result between the prefix and suffix. timeago provides temporary prefixes / suffixes, but not related to "publication", so they were added above.
To get rid of the space between the timeago_tag and time_posted_suffix (especially for the Japanese), I wrapped these tags with the %time< c < tag until I remove all spaces in the tag . This is a small thing, but for me it was annoying, so I wanted to insert it, but it is in no way necessary if you do not use languages ​​that need a value in the time_posted_suffix key. I also suggest that there is a better way to do this.

Questions

I originally had jquery.timeago.en.js , jquery.timeago.it.js and jquery.timeago.ja.js in the app / assets / javascripts / locales directory, but I had a problem when the en file did not load for en locale ; instead, the last file in alphabetical order in the directory that was ja will be used with en locale. So, I renamed the en file to jquery.timeago.xx.js , which displayed English. I tried moving the en file outside of the locales directory, but it seems to never fit, so it became xx.

Update

The problems with i18n that I had are now resolved. See this Github issue for more details. In the end, I got rid of my app / assets / javascripts / locales directory and put only jquery.timeago.ja.js , the only file I really wanted to set up in the lib / assets / javascripts / locales directory, which means for local :it and :en use the default translations timeago by default, and the translations :en displayed as expected. So, I got what I think is a good solution to this rails-timeago stone rails-timeago .

Update 2

This solution currently works locally, but is not deployed correctly in Heroku due to problems with asset precompilation ...

Update 3

Found a configuration solution that works locally and with Heroku:

configurations / 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 

<strong> configurations / environment / production.rb

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

And in this case, only the special file app / assets / javascripts / timeago / jquery.timeago.ja.js is required

More information can be found in the Github related issue .

+5
source

All Articles