Rails i18n practices

Rails gives us localization features via the rails-i18n gem. While the Rails guide describes the technical details on how to use it, it doesn't prescribe any guidelines on how to name and sort your localization strings. Here's my take on how a project's I18n strings should be sorted out.


Quote your strings

While the YAML format is liberal and quotation marks aren't needed, the consistency is always welcome. It also makes it less ambiguous for non-developers who may edit the YAML file.

en:
  posts:
    index:
      title: "Blog posts"
      description: "These are the latest posts in the blog."

Don't add punctuation

Some strings end in :. Don't place them in the YAML file. This will allow for the strings to be reusable later on.

t('.categories') + ":"

Group by controller and action

Place your page's strings under their respective controller and action names. This allows to you take advantage of Rails's shortcuts. Also, always name your primary title as title.

# looks up 'posts.index.title', if you're on the posts#index view
t('.title')

See: lazy lookup (guides.rubyonrails.org)

Group strings for partials

The same concept should apply for partials. You can also use the t('.login') shortcut inside partial views.

en:
  shared:
    nav:
      back_to_home: "Back to home"
      login: "Log in"

Avoid top-level strings

Don't place strings on the top level such as t('and'). Place them on a parent, even an arbitrary one. If you can't think of a parent name, use common.

en:
  actions:
    submit: "Submit"
    add: "Add"
    delete: "Delete"
    login: "Log in"
  common:
    or: "or"
    and: "and"

Avoid over nesting

Prefer to nest with just one level. Overly-complicated nesting can seem very arbitrary and confusing.

# Avoid
en:
  user:
    mail:
      status:
        delivered: "Delivered"
        read: "Read"
# Better
en:
  mail_status:
    delivered: "Delivered"
    read: "Read"

Familiarize yourself with defaults

The default locale file is available under rails-i18n.

See: locale/en.yml. (svenfuchs/rails-i18n)


Time and date

Don't use .strftime

Use i18n to format timestamps. Define your time formats in time.formats. Listed below are the default time formats available in Rails.

l(Time.now, format: :short)
en:
  time:
    formats:
      default: "%a, %d %b %Y %H:%M:%S %z"
      short: "%d %b %H:%M"

Same with dates

The I18n.l method also supports dates. Also, when creating new formats, add comments on what they should look like to help your teammates along.

l(Date.today, format: :long)
en:
  date:
    formats:
      default: "%Y-%m-%d" # 2015-06-25
      long: "%B %d, %Y"   # June 25, 2015
      short: "%b %d"      # Jun 25

See: Adding date time formats (guides.rubyonrails.org)


Forms

Use ActiveRecord errors

The Rails method full_messages looks up in predefined locations in your locale file. Take advantage of them. See the cheatsheet for more.

person = Person.create
person.errors.full_messages
#=> ["Name is too short (minimum is 5 characters)",
#    "Name can't be blank", "Email can't be blank"]
activerecord.errors.models.[model_name].attributes.[attribute_name].[error]
activerecord.errors.models.[model_name].[error]
activerecord.errors.messages.[error]
errors.attributes.[attribute_name].[error]
errors.messages.[error]

See: Translations for the errormessagesfor helper (guides.rubyonrails.org)

Use form labels

There are also conventions on where f.label will look up labels.

form_for @post do
  f.label :body
helpers:
  # helpers.label.<model>.<field>
  label:
    post:
      body: "Your body text"