Files
nairobi/docs/en/features/globalize.md
Pietro Monticone f62cd1129b Clean docs
2022-11-01 15:20:25 +01:00

5.0 KiB

Globalize

Follow this steps to add Globalize to a model (the gem globalize_accessors is also used).

1. Define the attributes to be translated

We should add in the model the attributes that are going to be translated. To do that, use the translates option followed by the attribute names.

We also need to add the option globalize_accessors to include all the locales we want to support. This gem generates all the methods needed by the application (title_en, title_es, etc.). If you want to include all the translated fields in all the defined languages in your application, just call globalize_accessors without any option (as the documentation says).

# Supposing a model Post with title and text attributes

class Post < ActiveRecord::Base
  translates :title, :text
  globalize_accessors locales: [:en, :es, :fr, :nl, :val, :pt_br]
end

2. Create the migration to generate the translations table

We must create a migration to generate the table where the translations are going to be stored. The table must have a column for each attribute we want to translate. To migrate the stored data in the original table, add the option :migrate_data => true in the migration.

class AddTranslatePost < ActiveRecord::Migration
  def self.up
    Post.create_translation_table!({
      title: :string,
      text: :text
    }, {
      :migrate_data => true
    })
  end

  def self.down
    Post.drop_translation_table! :migrate_data => true
  end
end

3. Add the Translatable module

Add the Translatable module in the controller that will handle the translations.

class PostController < Admin::BaseController
  include Translatable
...

Make sure that the controller has the functions resource_model and resource, which return the name of the model and the object we want to save the translations for, respectively.

...
  def resource_model
    Post
  end

  def resource
    @post = Post.find(params[:id])
  end
 ...

4. Add the translation params to the permitted params

Add as permitted params those dedicated to translations. To do that, the module Translatable owns a function called translation_params(params), which will receive the object param and will return those keys with a value. It takes into account the languages defined for that model.

# Following the example, we pass the params[:post] because is the one that has the information.

attributes = [:title, :description]
params.require(:post).permit(*attributes, translation_params(params[:post]))

5. Add the fields in the form

Add the fields to the form for creating and editing the translations. Remember that, to do this, there is a function in the helper that encapsules the Globalize.with_locale logic in a block called globalize(locale) do.

The fields that are going to be translated should be named <attribute_name>_<locale>, for example title_en, so when that information arrives to the server, it can classify the parameters.

Remember that, to avoid errors when using locales like pt-BR, es-ES, etc. (those whose region is specified by a '-'), we must use a function called neutral_locale(locale), defined in the GlobalizeHelper. This function converts this type of locales in lower case and underscored, so pt-BR will transform in pt_br. This format is compatible with globalize_accessors, whereas the official is not because the method names like title_pt-BR are not allowed. When using this function, the method will call title_pt_br and it will not generate conflicts when comparing pt-BR with pt_br.

6. Add hidden parameters to delete translations

Add the hidden parameters to the form to delete translations:

<%= hidden_field_tag "delete_translations[#{locale}]", 0 %>

We must add the link "Remove translation" to delete translations, which should have:

  • an id with this format: delete-<neutral locale>, where "neutral locale" is the result of the function neutral_locale(locale).
  • an attribute data-locale with the value of neutral_locale(locale).
  • the class delete-language.
<%= link_to t("admin.milestones.form.remove_language"), "#",
                id: "delete-#{neutral_locale(locale)}",
                class: 'delete-language',
                data: { locale: neutral_locale(locale) } %>

The CSS styles and the rest of the classes will depend on the designed UI for that translations (if the link should show or hide, for example).

7. Add the translations for the new model to the dev_seed

So that they will be generated when the DB is restored. For example, to create a post whose description is translated.

section "Creating post with translations" do
  post = Post.new(title: title)
  I18n.available_locales.map do |locale|
    neutral_locale = locale.to_s.downcase.underscore.to_sym
    Globalize.with_locale(neutral_locale) do
      post.description = "Description for locale #{locale}"
      post.save
    end
  end
end