Add I18n translations to rspec tests

Not sure if this is optimal, but in my Rails3/RSpec2 apps, I test all my locale translations in RSpec in the following way:

I set the available locales in my config/initializers/i18n.rb file:

I18n.available_locales = [:en, :it, :ja]

and in my spec files that need translation checking I have tests that looks something like:

describe "Example Pages" do   

  subject { page }

  I18n.available_locales.each do |locale|

    describe "example page" do
      let(:example_text) { t('example.translation') }

      before { visit example_path(locale) }

      it { should have_selector('h1', text: example_text) }
      ...
    end
    ...   
  end
end

I wasn't sure how to get just the t() method to be usable in the specs without needing I18n.t so I just added a small convenience method to spec/support/utilities.rb:

def t(string, options={})
  I18n.t(string, options)
end

Update: These days I tend to use the i18n-tasks gem to handle testing related to i18n, and not what I wrote above or have answered on StackOverflow previously.

I wanted to use i18n in my RSpec tests primarily to make sure that I had translations for everything ie there were no translations missed. i18n-tasks can do that and more through static analysis of my code, so I don't need to run tests for all I18n.available_locales anymore (apart from when testing very locale-specific functionality, like, for example, switching from any locale to any other locale in the system).

Doing this has meant I can confirm that all i18n keys in the system actually have values (and that none are unused or obsolete), while keeping the number of repetitive tests, and consequently the suite running time, down.


In my code, a Rails 3 project, using RSpec 2, that is exactly the line I write:

describe "GET 'index'" do
  before do
    get 'index'
  end
  it "should be successful" do
    response.should be_redirect
  end

  it "should show appropriate flash" do
    flash[:warning].should == I18n.t('authorisation.not_authorized')
  end
end

So I am not sure why you say it is not possible?


Assuming the code in the controller is:

flash[:error] = I18n.translate 'error.discovered'

You could stub 'translate':

it "translates the error message" do
  I18n.stub(:translate) { 'error_message' }
  get :index # replace with appropriate action/params
  flash[:error].should == 'error_message'
end