Multilingual and I18N
All the languages files are in the config/locales/
folder.
There should be a sample file named en.yml
there. All the language files use the YAML format.
Take the “Home” wording as example. We can put the following code in the en.yml
file and then access it again with the translate method, or t as alias.
en:
home: "Home"
Using the locale in view:
<li><%= link_to translate('home'), root_path %></li>
Or we can have better organization by grouping the locales. This ensures we do not create conflicts with the same keys. Now in the en.yml
file.
en:
nav:
home: "Home"
And the view becomes:
<li><%= link_to translate('nav.home'), root_path %></li>
By grouping the locales, it ensures we do not create conflicts with the same keys.
And typing the translate()
method every time can be annoying. That’s why rails comes with an alias t()
:
<li><%= link_to t('nav.home'), root_path %></li>
Common Locales Setting
By default, the locale files comes with empty setting (Ignoring that hello world example). If you need some common local settings such as date and time. You can find it in this repo.
For date/time locals, please use localize
method, or l
, instead of the translate
.
Adding chinese
How about adding the Chinese supports?
Create a new file named zh-TW.yml
under the folder config/locales/
.
Put the following content into the file.
zh-TW:
nav:
home: "首頁"
Setting the default local to Chinese.
- Create a new file named locale.rb under the
config/initializers/
folder. - Put the following ruby code in the file. I18n.default_locale = "zh-TW"
- Restart the server.
Note: “zh-TW” or “zh-HK” is for Traditional Chinese. And “zh-CN” is for Simplified Chinese.
Before moving advance, let’s complete the navigation locale:
zh-TW:
nav:
home: "首頁"
login: "登入"
logout: "登出"
signup: "成為用戶"
And make sure we updated the view to use the locale setting. In the application.html.erb
file:
<nav>
<ul>
<li><%= link_to t('nav.home'), root_path %></li>
<% if user_signed_in? %>
<li><%= link_to "#{t('nav.logout')} (#{current_user.email})", destroy_user_session_path, :method => :delete %></li>
<% else %>
<li><%= link_to t('nav.login'), new_user_session_path %></li>
<li><%= link_to t('nav.signup'), new_user_registration_path %></li>
<% end %>
</ul>
</nav>
Switching locale
How about switching the locale?
Getting locale option from params.
In the application_controller.rb
file:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
Or
def set_locale
if params[:locale].in? %W(en zh-TW)
I18n.locale = params[:locale]
end
end
And now, we can access different with the params query: http://0.0.0.0:3000/?locale=en
.
Automatically appending the locale params to URL.
Rails comes with a default_url_options
that is the default query string and values that will be attached in the URL.
We can override the default_url_options
. Add the following method in the application_controller.rb
file.
def default_url_options
{ locale: I18n.locale }
end
This only applies to URL which is generated by rails, such as root_path
. Manually typing the URL will not get the default_url_options
attached.
And then we need the UI to switch. Since we want the language available everywhere, put it in the applicotian.html.erb
file.
<a href='?locale=zh-TW'>中</a> | <a href='?locale=en'>EN</a>
For more detail, please check I18n guide.