Chat with Thomas | Profile

Welcome to the Modern Web Design.

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.

  1. Create a new file named locale.rb under the config/initializers/ folder.
  2. Put the following ruby code in the file. I18n.default_locale = "zh-TW"
  3. 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.