#138
Dec 01, 2008

I18n

Internationalization is one of the biggest additions in Rails 2.2. See how the basics work in this episode.
Download (21.2 MB, 7:36)
alternative download for iPod & Apple TV (12.5 MB, 7:36)

Resources

<!-- users/new.html.erb -->
<p>
  <%= f.label :language, "Language" %><br />
  <%= f.select :language, [['English', 'en'], ['Wookieespeak', 'wk']] %>
</p>

<!-- products/index.html.erb -->
<% title t('welcome.title') %>
<p><%= t 'welcome.paragraph' %></p>
<h2><%= t 'products.title' %></h2>
<% for product in @products %>
  <h3>
    <%= link_to h(product.name), product %>
    <%= number_to_currency(product.price) %>
  </h3>
  <div class="date_released">
    <em><%= t 'products.released' %>: <%= product.created_at.strftime("%m/%d/%Y") %></em>
  </div>
<% end %>
# sessions_controller.rb
flash[:notice] = t('flash.login')

# controllers/application.rb
before_filter :set_user_language
def set_user_language
  I18n.locale = current_user.language if logged_in?
end
# config/locales/en.yml
en:
  welcome:
    title: "Welcome"
    paragraph: "Thank you for visiting our store. Please browse through the products below and buy some stuff. You'll love the unique quality and workmanship put into these items."
  products:
    title: "Products"
    released: "Released"
  flash:
    login: "Logged in successfully."

# config/locales/wk.yml
wk:
  welcome:
    title: "Wyah"
    paragraph: "Wyaaaaaa. Ruh ruh. Huwaa muaa mumwa. Wyogg, ur oh. Wua ga ma uma ahuma ooma. Ruh gwyaaaag. Youw."
  products:
    title: "Mauhwaa"
    released: "Ruhhha"
  flash:
    login: "Wohooohaaa"
  number:
    format:
      precision: 3
      separator: '|'
      delimiter: '-'
    currency:
      format:
        unit: '$'
        precision: 2
        format: '%u%n'

RSS Feed for Episode Comments 40 comments

1. MTH Dec 01, 2008 at 00:44

Yeah, that's what I need!

And now I can remove Globalite for sure 8-)

Thanks, Ryan!


2. Ben Dec 01, 2008 at 00:46

Nice Screencast!
All we need now is a good way to do model translation... :)


3. Andreas Dec 01, 2008 at 01:13

Great Screencast, thanks Ryan.
I've been doing apps in multiple languages for quite some time now. I started with ruby-gettext about 2 years ago and just switched to Rails i18n in a recent app. It's really great to have an API for i18n included in Rails.

For those who are interested in i18n - I'm posting thoughts, ideas and experiences with Rails i18n to my blog from time to time.


4. QuBiT Dec 01, 2008 at 01:23

Wookie wookie ^^ ...
or in other words ^^ ... just great.


5. Andreas Dec 01, 2008 at 01:25

Btw, I modified the rails-i18n repository with many core translations you mentioned and made it a plugin. I found it a bit easier and more maintanable to simply update a plugin instead of copy&pasting the core translations into my own .yml files every time.

The plugin can be found at http://github.com/zargony/rails-i18n


6. Andrew Dec 01, 2008 at 01:52

Another great Railscast! Sorry that this is off topic, but I've been using the instance variable @current_user in my Rails app. Would switching to the local variable reap any benefits (like speed improvements?) Thanks!


7. aurels Dec 01, 2008 at 02:40

Awsome!

Does anyone know if it will be possible to have some specific locale strings into engines?


8. Dejan Dimic Dec 01, 2008 at 02:42

Any decent web application need to have localisation sooner or latter. Now this task is much easer and this screen cast is great first step in localisation process.


9. David Trasbo Dec 01, 2008 at 02:54

This is just what I have been waiting for! Thanks, Ryan.

@Andrew: Try asking this question in the Ruby on Rails mailing list (or via http://www.ruby-forum.com/forum/3).


10. David Trasbo Dec 01, 2008 at 03:18

By the way, Ryan. I think you can mark this suggestion as 'completed': http://railscasts.uservoice.com/pages/general/suggestions/30459


11. Nils R Dec 01, 2008 at 03:51

Woohoo!

Have been waiting for this screencast. Will have to watch it when i'm back at home...


12. grigio Dec 01, 2008 at 06:18

Thanks for this screencast!!

@Ben:
For the model translation there is Globalize2 http://github.com/joshmh/globalize2/tree/master


13. Ryan Bates Dec 01, 2008 at 07:47

@Ben, I may cover model translation after this series on Rails 2.2 is done, thanks for the suggestion.

@Andrew, the "current_user" in my case is actually a method call. I prefer this over a before_filter which sets a @current_user because it will only load the current user if it needs access to it, not on every page all the time.

@David, thanks, marked.


14. Jean-Marc Dec 01, 2008 at 07:52

Translating the text and formats has always been important but it's half the battle when it comes to internationalization.

The other half is letting the user choose the language and having those pages being indexed in their specific languages.

I personally like to have the language as part of the URL because it makes for a very simple selection mechanism (and it makes every entities distinct one even for the search engines).

You have any thoughts on that level??


15. Ryan Bates Dec 01, 2008 at 07:58

@Jean, you could do this fairly easily with subdomains. Since the language is set in a before filter you could combine this episode with #123 on subdomains.
http://railscasts.com/episodes/123-subdomains


16. chovy Dec 01, 2008 at 09:44

Great screencast...the only thing missing is database translations.

Also, once you start translating the units of currency, you'll have to start converting prices from say "dollars to euros". Either dynamically based on the current exchange rate, or hard coded somewhere.


17. RailsCasts Fan Dec 01, 2008 at 11:35

Good work Ryan, like always. ;-)

i18n is very important and this screencast is a good start to start with internationalization.


18. Mark Wilden Dec 01, 2008 at 11:39

Locale is pronounced "loh-CAL".


19. Andreas Dec 01, 2008 at 11:58

@Jean-Marc: that should be easy. You could e.g. use a (configurable) constant hash as a tld=>locale lookup, e.g.

TLD_LANGS = { 'com' => 'en', 'de' => 'de' }

and use a before_filter in ApplicationController to set the locale based on the current request host like

I18n.locale = TLD_LANGS[request.host.split('.').last] || 'en'


20. Steve Dec 01, 2008 at 13:16

Is there any reason an application shouldn't display the preferred locale set in the browser? Is there an easy way to access this locale?


21. Michael Dec 01, 2008 at 15:47

Nice Screencast!

Maybe it is nice to add something like routes translations? Is that even possible?


22. qq Dec 01, 2008 at 17:13

handsome


23. Pawel Dec 02, 2008 at 01:33

Nice screencast, as always, thanks!

What if Wookie would like to enter some number in the form? The application needs to convert this number and probably save it to db. What are best practices to achive that?


24. Jean-Marc Dec 02, 2008 at 10:32

@Steve,

using the browser settings is one of the step toward presenting the correct language... at the same time limiting yourself to the preferred language of the browser would detract some of your users (for example, my browser here has a french default but I still prefer to view some sites in english, even when french is offered).

At the same time, you have to take in account that browsers are not the only client your website will have (I can still recall one website I was asked to look into, they were indexed in one of the three languages the site was available into... the reasons... language selection was done through cookies and search engines don't understand cookies).

The language selection process is important. I usually take an approach similar to the ibm.com website (having the locale being part of the url)... as Ryan suggests, sub-domains can achieve the same trick.

Jean-Marc


25. Quotes Dec 02, 2008 at 14:20

It is really great to be able to internationalize your application. We needed I18N for long time.

Thanks


26. Marc-Antoine Dec 03, 2008 at 13:32

Thanks again Ryan for this great tutorial. In the past, I have used Globalize to translate UI content. Sometimes when the layout was a little bit different from english to french, it was more easy just to create an other view to handle the job. Something like index.fr.html.erb. Can we do so in 2.2?

Thanks

Marc


27. pulkit Dec 03, 2008 at 21:43

Power Pack Performance of rails 2.2 !!!!


28. Andrea Dec 04, 2008 at 01:25

Thanks! Great episode! But what about models and validation translation? Is possibile with I18n? If so maybe you could show us how to with an advanced episode xD


29. Andreas Dec 04, 2008 at 03:15

@Andrea: Yes, models, attributes and validation messages can be translated as well as time/date formats or e.g. output of distance_of_time_in_words. You might want to have a look at the various "localized_dates" and "rails-i18n" repositories on github.


30. phaenotyp Dec 06, 2008 at 05:42

Woohoo!

Thank you, thank you, thank you!

Great screencast and exactly what I needed.


31. Josh Dec 07, 2008 at 15:19

Awesome screencasts... I've been a long-time fan.

Can you maybe give me a tip on what software you use to create these screencasts?

I'd like to produce some of my own, and yours are always very high quality. Any hints you can offer would be great!


32. Nando Vieira Dec 07, 2008 at 16:29

Make sure you check the plugin Localized Templates... translating long texts can be hard, so I prefer to have templates fully translated.

http://github.com/josevalim/localized_templates/


33. Gavin Laking Dec 08, 2008 at 05:04

Thanks again Ryan- great cast.

Josh: I think Ryan uses iShowU for his screencasts, but I expect he has a decent-ish microphone and setup because it sounds very clear and is well edited.

Gav


34. Josh Dec 08, 2008 at 13:54

@Gavin: Thanks for the tip!
I'll check out iShowU...


35. Qup Dec 09, 2008 at 07:37

@Mark Wilden

'Locale is pronounced "loh-CAL".'

It's not in my "loh-cAIL". ;-)


36. Jakob Skov-Pedersen Dec 11, 2008 at 07:24

This is cool I even created a Textmate command to help when localizing an existing app. Just select some text, and run it, it will ask for a desired translation name, and insert the appropriate <%=t 'name' %> for you. The translation line that you can insert into a yaml file is copied to the clipboard, ready for pasting ;) That makes it so much faster.

You can find it here if you're interested:
http://gist.github.com/31133


37. Slangasaurus Dec 11, 2008 at 09:48

My site is very language centric, and recently i used some fragment caching to speed up page loads. Has anyone tried I18n with fragment caching?


38. ohaleck Dec 12, 2008 at 03:15

Hurray! My voice has been heard!
Thank you so much Ryan for this screencast!!


39. Martin Dec 19, 2008 at 12:08

Why do I get ActionView::TemplateError (undefined method `each' for false:FalseClass) when I use <%= t 'hello' %> in a view??


40. IV Dec 25, 2008 at 01:46

Great RailsCast, thanks!
[pt] Grande Railscast, obrigado!

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player