Skip to content
larsp.de
Go back

Rails translation cheatsheet

How to translate a Rails application.

Locales

# config/application.rb

config.i18n.available_locales = %i[de fr it]
config.i18n.default_locale = :de
config.i18n.fallbacks = true

Add rails-i18n for ready-made date, number, and Active Record translations:

# Gemfile
gem "rails-i18n"

Locale files

# config/locales/de.yml
de:
  hello: "Hallo, %{name}!"
  apples:
    one: "1 Apfel"
    other: "%{count} Äpfel"
  pages:
    thankyou:
      title: "Danke"
      body_html: "<strong>Vielen Dank</strong> für deine Anfrage."

Use lazy lookup in views and controllers to avoid repeating the full key path:

# app/views/pages/thankyou.html.erb
<h1><%= t(".title") %></h1>
<%= t(".body_html") %>

A key ending in _html (or a leaf named html) is marked safe and rendered without escaping.

URL routing

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  around_action :switch_locale

  def switch_locale(&)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &)
  end

  def default_url_options
    { locale: I18n.locale }
  end
end
# config/routes.rb

scope "(:locale)", locale: /de|fr|it/ do
  get "thankyou", to: "pages#thankyou"
  get "terms", to: "pages#terms"

  resource :submissions, only: %i[new create]
  get "submissions", to: "submissions#new"
  get "/", to: "submissions#new"
end

Set lang on the layout so screen readers and search engines pick up the active locale:

# app/views/layouts/application.html.erb
<html lang="<%= I18n.locale %>">

A minimal locale switcher:

<% I18n.available_locales.each do |l| %>
  <%= link_to l.to_s.upcase, url_for(locale: l),
      class: ("active" if I18n.locale == l) %>
<% end %>

Dates and numbers

<%= l(Time.current, format: :short) %>
<%= number_to_currency(19.99) %>

rails-i18n ships the formats. Override them per locale under date.formats, time.formats, and number.*.

Models and validations

# config/locales/de.yml
de:
  activerecord:
    models:
      question:
        one: "Frage"
        other: "Fragen"
    attributes:
      question:
        question: "Frage"
        answer: "Antwort"
    errors:
      models:
        question:
          attributes:
            answer:
              blank: "muss ausgefüllt werden"

Question.model_name.human and Question.human_attribute_name(:answer) resolve these automatically, so form labels and validation messages stay translated without extra wiring.

Field translation

Translatable columns for Ruby on Rails, stored in the model table itself

# Gemfile
gem "traco"
# app/models/question.rb

class Question < ApplicationRecord
  translates :question, :answer
end

Traco expects per-locale columns like question_de, question_fr, question_it. For a heavier setup with a separate translations table, look at Mobility.

Finding missing keys

i18n-tasks scans the codebase for untranslated keys and unused entries:

bundle exec i18n-tasks missing
bundle exec i18n-tasks unused

Share this post on:

Previous Post
Dokku: Open source Heroku alternative
Next Post
Syncthing