Register now and start sharing your code snippets.
-->

How to use the new internationalization (I18n) API available in Rails 2.2

Ruby posted 2 months ago by christian

Not yet released, but you can try it out by first installing the i18n gem:

   1  sudo gem install i18n 

And then testing the following code:

   1  require 'rubygems'
   2  require 'i18n'
   3  
   4  I18n.store_translations 'en-US',
   5  	:yes => "yes",
   6  	:no => "no", 
   7  	:inbox => {
   8  	  :one => '1 message', 
   9  	  :other => '{{count}} messages'
  10  	}
  11  
  12  I18n.store_translations 'sv',
  13  	:yes => "ja",
  14  	:no => "nej", 
  15  	:inbox => {
  16  	  :one => '1 meddelande', 
  17  	  :other => '{{count}} meddelanden'
  18  	}
  19  
  20  I18n.locale = 'en-US'
  21  
  22  puts I18n.translate(:yes)
  23  puts I18n.translate(:inbox, :count => 1)
  24  puts I18n.translate(:inbox, :count => 2)
  25  puts I18n.localize Time.now
  26  
  27  
  28  I18n.locale = 'sv'
  29  
  30  
  31  puts I18n.translate(:yes)
  32  puts I18n.translate(:inbox, :count => 1)
  33  puts I18n.translate(:inbox, :count => 2)
  34  puts I18n.localize Time.now

Troubleshooting

Note that the gem doesn’t contain localization data, so you’ll get the following error:

   1  translation missing: en-US, time, formats (I18n::MissingTranslationData)

To fix this, simply tell the I18n gem where to find the locales you want to use:

   1  I18n.load_translations "#{RAILS_ROOT}/locales/#{locale}.rb"

Creating a shortcut for i18n.translate

I recommend you create a shortcut for I18n.translate to the Symbol and String classes:

   1  class Symbol
   2  	def t(params = {})
   3  		I18n.t(self, params)
   4  	end
   5  end
   6  
   7  class String
   8  	def t(params = {})
   9  		I18n.t(self.to_s, params)
  10  	end
  11  end
  12  

Now instead of this:

   1  puts I18n.translate(:yes)
   2  puts I18n.translate(:inbox, :count => 1)
   3  puts I18n.translate(:inbox, :count => 2)

You can type:

   1  puts :yes.t
   2  puts :inbox.t(:count => 1)
   3  puts :inbox.t(:count => 2)

Handling missing translations

You can use this code to change the default behavior for missing translations, instead of showing “Missing translation” this code allows you to log the missing translation:

   1  class Symbol
   2    def t(params = {})
   3      params.update({:raise => true})
   4  
   5      begin
   6        I18n.t(self, params)
   7      rescue I18n::MissingTranslationData
   8        RAILS_DEFAULT_LOGGER.info("Translation for '#{self}' is missing")
   9        self
  10      end
  11    end
  12  end
  13  
  14  
  15  class String
  16    def t(params = {})
  17      params.update({:raise => true})
  18      key = self.downcase.to_s
  19        
  20      begin
  21        I18n.t(key, params)
  22      rescue I18n::MissingTranslationData
  23        RAILS_DEFAULT_LOGGER.info("Translation for '#{key}' is missing")
  24        self
  25      end
  26    end
  27  end

References
  1. http://github.com/svenfuchs/i18n/
  2. http://github.com/clemens/i18n_demo_app/
  3. http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api
  4. How to use the new I18n API with Rails

Tagged ruby, rails, i18n

How to fix "Only get, head, post, put, and delete requests are allowed."

Ruby posted 2 months ago by christian

I’m getting this once in a while in development mode after changing the routes configuration:

   1  ActionController::MethodNotAllowed
   2  
   3  Only get, head, post, put, and delete requests are allowed.

The solution for me has been to restart the server.

Tagged bug, rails, problem, fix

How to SEO optimize your Rails URLs and routes

Ruby posted 2 months ago by christian

My idea for achieving optimal content crawlability and SEO optimized URLs is to use permalinks instead of ids and the default Rails routes. The permalinks can contain whatever you decide is optimal from a SEO point of view.

As an example, let’s take a recipe site that has a recipe at http://xxx/recipes/asia/china/beijing-duck.html.

First let’s configure the .html extension to be handled by the RecipesController:

   1  map.connect 'recipes/*permalink.html', :controller => 'recipes', :action => 'show'

In the code we use the URI , which is the permalink of the recipe, to retrieve the recipe from the database:

   1  class RecipesController
   2    def show
   3      @product = Recipe.find_by_permalink(request.path)
   4    end
   5  end

To handle the categories and subcategories, we use the following route:

   1  map.connect 'recipes/*permalink/', :controller => 'categories', :action => 'show'

And create the CategoriesController:

   1  class CategoriesController
   2    def show
   3      @category = Category.find_by_permalink(request.path)
   4    end
   5  end

Now what’s left is for you to figure out how to generate the permalinks… I recommend having a look at permalink_fu.

Tagged seo, rails, routes, permalink, crawlability

How to localize Rails routes

CSS posted 2 months ago by christian

I forget this all the time:

   1  map.resources :products, :as => 'productos', :path_names => { :new => 'nuevo', :edit => 'editar' }

Documented here….

Tagged resources, routes, localize, rails

Time ago in words (minutes, hours, days, weeks, months ago in words)

Ruby posted 4 months ago by christian

   1  def minutes_in_words(timestamp)
   2      minutes = (((Time.now - timestamp).abs)/60).round
   3      
   4      return nil if minutes < 0
   5      
   6      case minutes
   7        when 0..4            then '&lt; 5 minutes'
   8        when 5..14           then '&lt; 15 minutes'
   9        when 15..29          then '&lt; 30 minutes'
  10        when 30..59          then '&gt; 30 minutes'
  11        when 60..119         then '&gt; 1 hour'
  12        when 120..239        then '&gt; 2 hours'
  13        when 240..479        then '&gt; 4 hours'
  14        when 480..719        then '&gt; 8 hours'
  15        when 720..1439       then '&gt; 12 hours'
  16        when 1440..11519     then '&gt; ' << pluralize((minutes/1440).floor, 'day')
  17        when 11520..43199    then '&gt; ' << pluralize((minutes/11520).floor, 'week')
  18        when 43200..525599   then '&gt; ' << pluralize((minutes/43200).floor, 'month')  
  19        else                      '&gt; ' << pluralize((minutes/525600).floor, 'år')
  20      end
  21    end

There are also similar implementations:
  1. http://www.actsasflinn.com/articles/2007/04/10/time-ago-method-for-ruby-on-rails
  2. http://timeago.yarp.com/
Tagged month, week, hour, minutes, words, rails, ruby