Refactor I18n

Sergey Pchelintsev @jalkoby

My app has only one UI language.

Why do I have to care about it?

Be flexible and open to change

Texts become a content

(which is not your responsibility)

Avoid typos

%h1 Campaigns

%a(href="#") Create a new campaign
%a(href="#") Export campaings

%table
  %tr
    %th Name
    %th Created At
    %th Actions
  - @campaigns.each do |campaign|
    %tr
      %td= campaign.name
      %td= campaign.created_at
      %td
        %a(href="#") Veiw

To be popular a technology needs

a good tool & a predictable defaults 

The tool

i18n_info = { 
  backends: [
    { [:yaml, :ruby] => :default }, :redis, 
    :sql_db, :'3rd party services'
  ],
  live_reload: true,
  interpolation: true,
  pluralisation: true,
  # I18n.t 'models.user', count: count
  # # count == 0 -> models.user.zero || models.user.other
  # # count == 1 -> models.user.one
  # # else -> models.user.other
  default: true
  # I18n.t 'some.key', default: [
  #  :'use.like.i18n.path', 
  #  "if the previous default doesn't exist"
  # ]
}

The defaults

the missing part

Commons

# app/helpers/application_helper.rb
def t_c(key, options = {})
  t :"#{controller_name}.common.#{key}", default: :"common.#{key}"
end

def save_btn
  submit_tag t_c(:save), # a long list of other attributes
end

en:
  common:
    save: Save
  feedback:
    common:
      save: Send

Models & Attributes

# app/helpers/application_helper.rb
def t_attr(key, model_name = nil)
  model_name = resolve_model_name(model_name)
  t “activerecord.attributes.models.#{model_name}, default: :“attributes.#{key}”
end

def t_r(model_name = nil)
  model_name = resolve_model_name(model_name)
  t “activerecord.models.#{model_name}, count: 1
end

def t_rs(model_name = nil, count = 10)
  model_name = resolve_model_name(model_name)
  t “activerecord.models.#{model_name}, count: count
end

def resolve_model_name(value)
  value || controller_name.singularize
end
{ en: {
  attributes: { created_at: 'Created at', name: 'Name' },
  activerecord: { 
    attributes: { models: { email: { created_at: 'Sent at' } },
    models: { email: { one: 'E-Mail', other: 'E-Mails' } }
  },
}}

Actions

# app/helpers/application_helper.rb
# t_a :create
# t_a :update, :user, few: true
# t_a :export, few: true
def t_a(name, *args)
  custom = args.extract_options!
  model = custom.delete(:few) ? t_rs(args[0]) : t_r(args[0])
  options = {
    default: :“actions.base.#{name}”, 
    model: model.downcase
  }.merge(custom)
  t “actions.#{model_name}.#{name}, options 
end
en:
  actions:
    base:
      created: "The %{model} has been created"
      updated: "The %{model} has been updated"
      deleted: "The %{model} has been deleted"
    email:
      created: "The E-Mail has been sent"

All together

# campaigns#index
%h1= t_rs

%a(href="#")= t_a :create
%a(href="#")= t_a :export, few: true

%table
  %tr
    %th= t_attr :name
    %th= t_attr :created_at
    %th= t_c :actions
  - @campaigns.each do |campaign|
    %tr
      %td= campaign.name
      %td= campaign.created_at
      %td
        %a(href="#")= t_c :view

The basic idea will be there

https://github.com/jalkoby/tt

¡Gracias!

¿sus preguntas?

Refactor I18n

By Sergey Pchelincev

Refactor I18n

  • 1,581