- Languages are
:en
and:ja
and:fr
, where:en
is the default. - It is path-based, like
/ja/articles
is for Index of Article model. - Allow access without the locale parameter in the path like
http://example.com/articles
- in which case the locale parameter
I18n.locale
should be set according to the browser's request, falling back to:en
- in which case the locale parameter
gem 'rails-i18n', '~> 6.0' # For 6.0 or higher
gem 'i18n-timezones'
gem 'devise-i18n'
In /config/application.rb
# Permitted locales available for the application
I18n.available_locales = [:ja, :en, :fr]
You may or may not set I18n.default_locale = :en
# /config/environments/production.rb
config.i18n.fallbacks = [:en, :ja, :fr]
(c.f., Stackoverflow)
Set this only in production.rb
so that developers would be more likely to notice missing Translations in the Development and Test environments.
# /config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:ja) do |inflect|
end
This prevents the fallback (usually active only in Production) from Japanese (:ja
) in inflection (pluralize
, singularize
) to English.
# /config/routes.rb
# should be placed at the top(!)
filter :locale
default_url_options(locale: I18n.locale) if Rails.env.test?
The reason the latter is necessary for the Test environment is complicated. See my question at Stackoverflow
Rails I18n Guide tells the following is better to allow the access without the local parameter in the path and also the root directory with a locale parameter. However, it is working in my environment without these (perhaps because I am using routing-filter Gem?
# config/routes.rb
scope "(:locale)", locale: /en|ja|fr/ do
resources :books
end
# To take care of the root path, place immediately before: root to: "home#index"
get '/:locale' => 'home#index'
# /app/controllers/application_controller.rb
# This should come AFTER the Devise authentication(?)
around_action :switch_locale
def default_url_options(options={})
#Rails.application.default_url_options = Rails.application.routes.default_url_options = { locale: I18n.locale }
{ locale: I18n.locale }.merge options
end
protected
# From https://guides.rubyonrails.org/i18n.html#managing-the-locale-across-requests
def switch_locale(&action)
locale = (params[:locale].blank? ? I18n.default_locale : params[:locale])
I18n.with_locale(locale, &action)
end
# /test/test_helper.rb
RoutingFilter.active = false
Get the current locale with I18n.locale To temporary set a locale in a block, do (Stackoverflow):
I18n.with_locale(:nl) do
link_to('nl', params.merge(id: category.name))
end
# `config/locales/fr.yml`
fr:
Ta: Merci
common:
hello: "Bonjour %{name}"
Then call
I18n.translate :Ta
I18n.t('common.hello', name: "Mary", default: [:"common.hi", "Hello, Mary"]) %>
The latter means
- Try
common.hello
with the local variablename
- Failing it, it tries
common.hi
- Failing it, the final default fallback is "
Hello, Mary
".
Note: In Views and helpers, t()
is the short-form of I18n.translate
Also, .keyword
is available in Views; for example,
es:
books:
index:
title: "Título"
then it can be called from the corresponding view like:
<%# app/views/books/index.html.erb %>
<%= t '.title' %>
- Rails I18n guide
- Stackoverflow: Rails default_url_options conflicts with params in path/url-helpers
- Stackoverflow: my answer about pluralize and inflection