Rails 2.2 was released late November, about two weeks ago. Of all the new features, one of the most prominent is the out-of-the-box implementation of internationalization (i18n, because it has 18 letters between I and N) in the new Rails 2.2 generated application (using the rails command).
Before we dive into the implementation, we’re going to discuss a bit of the evolution of this solution.
In the Good Old Days (possibly before the Internet was widespread in usage), applications hard-coded their strings. So if you had a login form/box/control/screen/something, you’d have something like:
Login:
Password:
What, then, happens if you want to translate your application into another language like French? You could always hard-code the new values, and maintain a second version; but that’s expensive to maintain.
Then an idea emerged–how about storing the strings in a file somewhere, and using some sort of class to get the strings?
So you might have a class like this:
class LanguagePack
def get_string(string_key)
# open up a text file specified in LanguageManager.language
# look for the line with string_key
# return the actual text
end
end
This class contains the strings. Accompanying this would be the strings file, like so:
# en.txt
password = Password:
login = Login:
To obtain strings, you ask the LanguageManager, like so:
class LanguageManager
attr_accessor :language
def get_string(key)
LanguagePack.get_string(key)
end
end
So you can do things like this:
LanguageManager.get_string("password") # => "Password: "
LanguageManager.language = "fr" # use French, search fr.txt
LanguageManager.get_string("password") # => "Mot de Passe: "
As you can see, changing languages is easy–just call LanguageManager.language = fr", for example, to use French. C’est bon!
Your form would then be:
<%= LanguageManager.get_string(login) %>
<%= LanguageManager.get_string(password) %>
And this is precisely how Rails 2.2 handles internationalization! The above form is written as:
<%= I18n.t :login %>
<%= I18n.t :password %>
Why? Because I18n.t takes a string key, and returns the text, like so:
I18n.t("login") => "Login: "
I18n.t("password") => "Password: "
Where are the actual keys and strings stored? They’re inside config/locales/LANGCODE.yml. For example, English keys (since English is the default language) are stored in en.yml.
When you invoke the rails command to build a new app, by default, en.yml will have these contents:
# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
hello: "Hello world"
You can easy add new strings; for our input form, we’d use something like:
login: "Login: "
password: "Password: "
# ...
And so on. Also, note that in your environment.rb file, there’s a new (commented-out) line, like so:
# config.i18n.default_locale = :de
You can uncomment this to set the default locality to German. Or French. Or Japanese. Or Arabic. Or whatever you want!
Also, what about templated strings–like “Hello, <your name>?” The solution is something well-used in different programming languages–simply use a token in your string, and spcify the value on-the-fly, like so:
# in en.yml
greeting: Hello, {first_name}!
# in the code
<%= I18n.t :greeting, :first_name => "Muhammad" # => Hello, Muhammad!
Finally, how do you change the locale? By specifying I18n.locale, like so:
I18n.locale = "de-DE" # German
There’s more to it than this, but we’ll leave it at this for now. So enjoy!
And don’t forget the key lesson of this whole shpiel–internationalize your application! Gone are the days of relying on just one language! The web is too big! (And your users will love you for it!)
Nice post. There a couple small mistakes though:
- Internationalization has 20 letters: i + 18-letters + n
- I18n.locale = “de-DE” # Dutch should say: I18n.locale = “de-DE” # German or Deutsch in native
Dutch is the languages spoken in the Netherlands and Deutsch is how you say German in German.
Oops! Good catch, thanks. I was always confused about Dutch vs. Deutsch.
thanks
your article is helpful…
can u make this article more like a tutorial…
That would be really helpful for people like me
:)
Not sure how to make it more tutorial-like….
1) Just substitute strings for I18n.t :key
2) And key: value pairs into en.yaml
That’s it!
A nice idea to first show a simple self-made solution and then compare it to the official framework.
I have also written an overview about the rails internationalisation, with some details about validation messages. See link above.