
Rails i18n: Complete Ruby on Rails Internationalization Guide
From first locale file to production: configure Rails I18n, use the t() helper, handle CLDR pluralization, fix common pitfalls, and add smart locale fallback chains.
Understand Rails I18n Architecture
Rails ships with the I18n gem built in. Translation files live in config/locales/ as YAML (default) or Ruby files. The framework provides the t() helper (alias for I18n.translate) in views, controllers, models, and mailers. Rails I18n is simple by design — it handles basic translation, interpolation, and pluralization out of the box.
# Rails includes i18n out of the box via the i18n gem
# config/application.rb
module MyApp
class Application < Rails::Application
# Default locale
config.i18n.default_locale = :en
# Available locales
config.i18n.available_locales = [:en, :de, :ja, :es, :fr, :'pt-BR']
# Fallback to default locale when translation is missing
config.i18n.fallbacks = true
# Load translations from nested directories
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
end
end# config/routes.rb
Rails.application.routes.draw do
scope "/:locale", locale: /en|de|ja|es|fr|pt-BR/ do
root "home#index"
resources :products
end
root "home#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
around_action :switch_locale
private
def switch_locale(&action)
locale = params[:locale] || I18n.default_locale
I18n.with_locale(locale, &action)
end
def default_url_options
{ locale: I18n.locale }
end
endConfigure Locale Settings
Set default_locale, available_locales, and fallback behavior in config/application.rb or an initializer. Configure locale detection in your ApplicationController using before_action to set the locale from the URL, session, cookie, or Accept-Language header.
# config/locales/en.yml
en:
nav:
home: "Home"
about: "About"
settings: "Settings"
greeting: "Hello, %{name}!"
cart:
item_count:
one: "%{count} item"
other: "%{count} items"
# config/locales/de.yml
de:
nav:
home: "Startseite"
about: "Über uns"
settings: "Einstellungen"
greeting: "Hallo, %{name}!"
cart:
item_count:
one: "%{count} Artikel"
other: "%{count} Artikel"Use the t() Helper
The t() helper is available everywhere in Rails — views, controllers, models, mailers, and jobs. It accepts a key, optional interpolation variables, and options like default values and scope. In views, Rails supports lazy lookups that automatically scope keys to the current controller and action.
# In views (ERB)
<h1><%= t('nav.home') %></h1>
<p><%= t('greeting', name: @user.name) %></p>
# In controllers
flash[:notice] = t('flash.product_created')
# In models
validates :name, presence: { message: I18n.t('errors.blank') }
# With HTML (safe)
<%= t('terms_html', link: link_to(t('terms_link'), '/terms')) %>Handle Pluralization
Rails I18n uses CLDR plural categories: zero, one, two, few, many, other. English only needs one and other, but other languages need more forms. Define plural translations as nested YAML keys under the count categories your target languages require.
# In YAML:
en:
cart:
item_count:
zero: "No items"
one: "%{count} item"
other: "%{count} items"
# Arabic (6 forms):
ar:
cart:
item_count:
zero: "لا عناصر"
one: "عنصر واحد"
two: "عنصران"
few: "%{count} عناصر"
many: "%{count} عنصرًا"
other: "%{count} عنصر"
# Usage in views:
<%= t('cart.item_count', count: @cart.items.size) %>Add Locale Fallback Chains
Rails' built-in I18n.fallbacks only provides a basic fallback from regional to default locale. A pt-BR user with a missing key sees English instead of pt-PT. rails-locale-chain adds configurable deep-merge chains so regional users always see the closest available translation.
# Lazy lookups use the controller/action as scope
# app/views/products/index.html.erb
# Instead of t('products.index.title'), just use:
<h1><%= t('.title') %></h1>
<p><%= t('.description') %></p>
# Rails looks up: products.index.title and products.index.description
# config/locales/en.yml
en:
products:
index:
title: "All Products"
description: "Browse our catalog"Automate Translations
With your Rails I18n setup complete, translate your YAML locale files using AI. i18n Agent supports YAML natively — point it at your source locale file and it generates all target languages, preserving nested keys, interpolation variables, and plural forms.
# Gemfile
gem 'rails-locale-chain'
# config/initializers/locale_chain.rb
Rails.application.config.i18n.fallbacks = {
'pt-BR': ['pt', 'en'],
'zh-Hant-TW': ['zh-Hant', 'zh', 'en'],
'es-419': ['es', 'en'],
}
# The gem deep-merges translations across the chain
# pt-BR -> pt -> en
# Missing keys in pt-BR are filled from pt, then enCommon Pitfalls
InvalidPluralizationData Errors
Lazy Lookups Outside Views
YAML Syntax Errors Break All Translations
Try i18n Agent Now
Drop your translation file here
JSON, YAML, PO, XML, CSV, Markdown, Properties
or click to browse
Target languages