AyuntamientoMadrid/participacion

View on GitHub
docs/en/features/globalize.md

Summary

Maintainability
Test Coverage
# Globalize

Follow this steps to add [Globalize](https://github.com/globalize/globalize) to a model (the gem [`globalize_accessors`](https://github.com/globalize/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](https://github.com/globalize/globalize-accessors#example) says).

```ruby
# 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.

```ruby
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.

```ruby
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.

```ruby
...
  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.

```ruby
# 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:

```erb
<%= 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`.

```erb
<%= 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.

```ruby
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
```