Internationalization
This article will teach you how to translate your Rails application into different languages, how to work with translations, and how to switch locales.
Table of Contents
- What is Internationalization?
- Ruby I18n (Internationalization)
- Create translation
- Translate with parameter
- Model Translation
- Language Switcher
What is Internationalization?
Internationalization is a development approach that makes it easier to adapt a project to the language and cultural differences of a location other than the one where it was created.
Ruby I18n (Internationalization)
Rails applications has a built-in I18n
gem, which is a comprehensive internationalization tool. I18n is a simple and extensible framework for translating the application to a single custom language other than English or for implementing multi-language support in applications. By default, the language of I18n is English.
Create translation
To do our multilingual feature, we need to create the translation vocabulary file (YAML) with its name based on the language locale code, then afterward, call the I18n function to replace the hard-coded content in the template.
Let’s make our posts page an example. Go to config/locales
and open en.yml
file. The en.yml
file contains your vocabulary for english. Add another translation for post list.
# config/locales/en.yml
en:
hello: "Hello world"
+ post_list: Post List
Two spaces must be used for indentation in YAML format. Always check the indention of your yaml file carefully.
Change the posts page header, call the translation method.
<!-- app/views/posts/index.html.erb -->
- <h1>Post List</h1>
+ <h1><%= t('post_list') %></h1>
<!-- ... -->
Read Carefully:
The method
t
is short forI18n.t
, it is a Helper method that will replace strings according to the language it belongs.
Now, let’s try making a translation for Chinese. The I18n locale code for simplified chinese is zh-CN
.
# config/locales/zh-CN.yml
zh-CN:
post_list: 活動清單
To change language, just set I18n.locale
with the language locale code. To make an example, let’s change language temporarily.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
#...
def index
+ I18n.locale = 'zh-CN'
#...
end
Translate with parameter
In some instances, a sentence may require a variable, for cases like this, we can use %{variable_name} syntax in our translation. Let’s try making a translation with parameter.
# config/locales/en.yml
# ...
en:
- hello: "Hello world"
+ hello: "Hello, %{name}"
post_list: Post List
# config/locales/zh-CN.yml
zh-CN:
+ hello: "您好, %{name}"
post_list: 活動清單
Display it in our application layout.
<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<!-- ... -->
<%= t( 'hello', name: current_user.email) if current_user %>
<%= yield %>
</body>
</html>
Model Translation
Model name and its attributes can also have a translation.
# config/locales/model.en.yml
en:
activerecord:
models:
post:
one: Post
other: Posts
attributes:
post:
title: Title
content: Content
# config/locales/model.zh-CN.yml
zh-CN:
activerecord:
models:
post:
one: 文章
other: 多篇文章
attributes:
post:
title: 標題
content: 內容
Separating your translations to make your code organized and clean is a good practice.
Read Carefully:
The translations file name makes no difference, the important thing is that the first layer in the YAML structure corresponds to the name of the locale. Rails will load all the YAML vocabulary file from
config/locales
.
Call Model.human_attribute_name(:name)
to use the translation. Change the table header in posts page.
<!-- app/views/posts/index.html.erb -->
<table>
<thead>
- <td>title</td>
- <td>content</td>
+ <td><%= Post.human_attribute_name(:title) %></td>
+ <td><%= Post.human_attribute_name(:content) %></td>
Language Switcher
Now that we’ve finished the translations, let’s get started on the switch language feature.
Remove the hardcoded setup of locale language on posts controller index.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
#...
def index
- I18n.locale = 'zh-CN'
#...
end
Setup the config for default locale, and available locales.
# config/application.rb
# ...
module App
class Application < Rails::Application
# ...
+ config.i18n.default_locale = :en
+ config.i18n.available_locales = [:en, 'zh-CN']
# Don't generate system test files.
config.generators.system_tests = nil
end
end
Then start making the locale setter on our application controller.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
+ before_action :set_locale
+
+ def set_locale
+ if params[:locale] && I18n.available_locales.include?( params[:locale].to_sym )
+ session[:locale] = params[:locale]
+ end
+
+ I18n.locale = session[:locale] || I18n.default_locale
+ end
# ...
end
Finally, add a link for switching language on our application layout.
<!-- app/views/layouts/application.html.erb -->
<!-- ... -->
+ <%= link_to 'EN', params.permit!.merge(locale: 'en') %>
+ <%= link_to 'zh-CN', params.permit!.merge(locale: 'zh-CN') %>
<%= yield %>
</body>
</html>
That is all for internationalization.