6.2 Customize: Internationalization

Jonathan Allard edited this page Jul 13, 2016 · 4 revisions

Overview

Wikipedia defines Internationalization as:

In computing, internationalization and localization (also spelled internationalisation and localisation, see spelling differences) are means of adapting computer software to different languages and regional differences. Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes. Localization is the process of adapting internationalized software for a specific region or language by adding locale-specific components and translating text.

The numeronym I18n is a number based word that is an abbreviation for the word “internationalization”. The term “I18n” is derived from its spelling as the letter “i” plus 18 letters plus the letter “n”.

I18n Resources

While, the concept is simple, implementing internationalization and localization can be complex and involved. Fortunately, Rails (version 2.2 and later) and the Rails community make the process much easier.

Here are resources (with links to additional resources) that can be used by anyone new to internationalization/localization:

Formtastic and I18n: Basic Localization

Formtastic has some neat I18n-features. ActiveRecord object names and attributes are, by default, taken from calling @object.human_name and @object.human_attribute_name(attr) respectively. There are a few words specific to Formtastic that can be translated. See lib/locale/en.yml for more information.

Basic localization (labels only, with ActiveRecord):

  <% semantic_form_for @post do |form| %>
    <%= form.input :title %>        # => :label => I18n.t('activerecord.attributes.user.title')    or 'Title'
    <%= form.input :body %>         # => :label => I18n.t('activerecord.attributes.user.body')     or 'Body'
    <%= form.input :section %>      # => :label => I18n.t('activerecord.attributes.user.section')  or 'Section'
  <% end %>

Note: This is perfectly fine if you just want your labels/attributes and/or models to be translated using ActiveRecord I18n attribute translations, and you don’t use input hints and legends. But what if you do? And what if you don’t want same labels in all forms?

Enhanced Localization (Formtastic I18n API)

Formtastic supports localized labels, hints, legends, actions using the I18n API for more advanced usage. Your forms can now be DRYer and more flexible than ever, and still fully localized. This is how:

1. Enable I18n lookups by default (config/initializers/formtastic.rb):

  Formtastic::FormBuilder.i18n_lookups_by_default = true

2. Add some cool label-translations/variants (config/locale/en.yml):

  en:
    formtastic:
      required: required field
      titles:
        post_details: "Post details"
      labels:
        post:
          title: "Choose a title..."
          body: "Write something..."
          edit:
            title: "Edit title"
      hints:
        post:
          title: "Choose a good title for you post."
          body: "Write something inspiring here."
      actions:
        create: "Create my {{model}}"
        update: "Save changes"
        dummie: "Launch!"

Note: We are using English here still, but you get the point.

3. …and now you’ll get:

  <% semantic_form_for Post.new do |form| %>
    <% form.inputs do %>
      <%= form.input :title %>      # => :label => "Choose a title...", :hint => "Choose a good title for you post."
      <%= form.input :body %>       # => :label => "Write something...", :hint => "Write something inspiring here."
      <%= form.input :section %>    # => :label => I18n.t('activerecord.attributes.user.section')  or 'Section'
    <% end %>
    <% form.buttons do %>
      <%= form.commit_button %>     # => "Create my {{model}}"
    <% end %>
  <% end %>

4. Localized titles (a.k.a. legends):

Note: Slightly different because Formtastic can’t guess how you group fields in a form. Legend text can be set with first (as in the sample below) specified value, or :name/:title options – depending on what flavor is preferred.

  <% semantic_form_for @post do |form| %>
    <% form.inputs :post_details do %>   # => :title => "Post details"
      # ...
    <% end %>
    # ...
<% end %>

5. Override I18n settings:

  <% semantic_form_for @post do |form| %>
    <% form.inputs do %>
      <%= form.input :title %>      # => :label => "Choose a title...", :hint => "Choose a good title for you post."
      <%= form.input :body, :hint => false %>                 # => :label => "Write something..."
      <%= form.input :section, :label => 'Some section' %>    # => :label => 'Some section'
    <% end %>
    <% form.buttons do %>
      <%= form.commit_button :dummie %>     # => "Launch!"
    <% end %>
  <% end %>

If I18n-lookups is disabled, i.e.:

  Formtastic::FormBuilder.i18n_lookups_by_default = false

…then you can enable I18n within the forms instead:

  <% semantic_form_for @post do |form| %>
    <% form.inputs do %>
      <%= form.input :title, :label => true %>      # => :label => "Choose a title..."
      <%= form.input :body, :label => true %>       # => :label => "Write something..."
      <%= form.input :section, :label => true %>    # => :label => I18n.t('activerecord.attributes.user.section')  or 'Section'
    <% end %>
    <% form.buttons do %>
      <%= form.commit_button true %>                # => "Save changes" (if we are in edit that is...)
    <% end %>
  <% end %>

6. Advanced I18n lookups

For more flexible forms; Formtastic can find translations using a bottom-up approach taking the following variables into account:

  • MODEL, e.g. “post”
  • ACTION, e.g. “edit”
  • KEY/ATTRIBUTE, e.g. “title”, :my_custom_key, …

…in the following order:

1. formtastic.{titles,labels,hints,actions}.MODEL.ACTION.ATTRIBUTE – by model and action
2. formtastic.{titles,labels,hints,actions}.MODEL.ATTRIBUTE – by model
3. formtastic.{titles,labels,hints,actions}.ATTRIBUTE – global default

…which means that you can define translations like this:

  en:
    formtastic:
      labels:
        title: "Title"  # Default global value
        article:
          body: "Article content"
        post:
          new:
            title: "Choose a title..."
            body: "Write something..."
          edit:
            title: "Edit title"
            body: "Edit body"

Values for labels/hints/actions are can take values: String (explicit value), Symbol (i18n-lookup-key relative to the current “type”, e.g. actions:), true (force I18n lookup), false (force no I18n lookup). Titles (legends) can only take: String and Symbol – true/false have no meaning.