From 212b280a8461a7890c096dda2fe9d4cd9039fb70 Mon Sep 17 00:00:00 2001 From: iagirre Date: Thu, 19 Apr 2018 16:16:18 +0200 Subject: [PATCH] Add documentation for Globalize Added documentation in spanish and english about how to make any attribute of any model transladable. --- docs/en/features/globalize.md | 122 +++++++++++++++++++++++++++++++++ docs/es/features/globalize.md | 123 ++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 docs/en/features/globalize.md create mode 100644 docs/es/features/globalize.md diff --git a/docs/en/features/globalize.md b/docs/en/features/globalize.md new file mode 100644 index 000000000..0c3bdce73 --- /dev/null +++ b/docs/en/features/globalize.md @@ -0,0 +1,122 @@ +# 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). + +``` +# 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 `_`, for example `title_en`, so when that information arrives to the server, it can clasify 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-`, 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 +``` \ No newline at end of file diff --git a/docs/es/features/globalize.md b/docs/es/features/globalize.md new file mode 100644 index 000000000..9a813abab --- /dev/null +++ b/docs/es/features/globalize.md @@ -0,0 +1,123 @@ +# Globalize + +Sigue estos pasos para añadir [Globalize](https://github.com/globalize/globalize) a un modelo de la aplicación (también se hace uso de la gema [`globalize_accessors`](https://github.com/globalize/globalize-accessors)). + +## 1. Definir los atributos a traducir + +Hay que definir los atributos que se quieran traducir en el modelo. Para ello, hay que añadir la opción `translates` seguida de los nombres de los atributos. + +También deberemos añadir la opción `globalize_accessors` con todos aquellos locales a los que queramos tener acceso. Esta gema generará los métodos `title_en`, `title_es`, etc., y que se usan en la aplicación. Si lo que quieres es incluir **todos** los campos traducidos en **todos** los idiomas definidos en tu aplicación, puedes llamar a `globalize_accessors` sin ninguna opción (tal y como se explica en la [documentación](https://github.com/globalize/globalize-accessors#example)). + +``` +# Suponiendo un modelo Post con attributos title y text + +class Post < ActiveRecord::Base + translates :title, :text + globalize_accessors locales: [:en, :es, :fr, :nl, :val, :pt_br] +end +``` + +## 2. Crear la migración para generar la tabla de traducciones + +Hay que crear una migración para generar la tabla donde se almacenarán todas las traducciones de ese modelo. La tabla deberá tener una columna por cada atributo que queramos traducir. Para migrar los datos ya almacenados (en la tabla original), hay que añadir la opción `:migrate_data => true` en la propia migración: + +``` +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. Añadir el módulo `Translatable` + +Añadir el módulo `Translatable` en el controlador que vaya a gestionar las traducciones. + +``` +class Post < Admin::BaseController + include Translatable +... +``` + +Hay que asegurarse de que este controlador tiene las funciones `resource_model` y `resource`, que devuelven el nombre del modelo y el objeto para el que se van a gestionar las traducciones, respectivamente. + +``` +... + def resource_model + Post + end + + def resource + @post = Post.find(params[:id]) + end + ... +``` + +## 4. Añadir los parámetros de las traducciones a los parámetros permitidos + +Añadir como parámetros permitidos aquellos que estén dedicados a las traducciones. Para eso, el módulo `Translatable` posee una función llamada `translation_params(params)`, a la que se le pasan el parámetro del objeto. A partir de esos parámetros, y teniendo en cuenta los idiomas definidos para ese modelo, la función devuelve aquellos parámetros que contengan un valor. + +``` +# Siguiendo con el ejemplo, en este caso se le pasarían los parámetros params[:post], porque es el +# hash que contiene toda la información. + +attributes = [:title, :description] +params.require(:post).permit(*attributes, translation_params(params[:post])) +``` + +## 5. Añadir los campos a traducir en los formularios + +Añadir los campos a los formularios de creación y edición para poder crear las traducciones. Recordar que, para esto, existe una función en el helper que engloba la lógica de `Globalize.with_locale` en un bloque llamado `globalize(locale) do`. + +Los campos que vayan a editar la información a traducir deberán llamarse `_`, por ejemplo `title_en`, de manera que, cuando esa información llegue al servidor, el helper pueda clasificar los parametros. + +Recuerda que, para evitar errores al usar locales como `pt-BR`, `es-ES`, etc. (aquellos cuya región está especificada por '-'), hay que utilizar la función `neutral_locale(locale)`, definida en el `GlobalizeHelper`. Esta función convierte este tipo de locales en minúsculas con guiones bajos, con lo que `pt-BR` pasará a ser `pt_br`. Este formato es compatible con `globalize_accessor`, al contrario que el oficial, puesto que los métodos generados tendrían el nombre `title_pt-BR`, que es un formato erróneo. Al usar esa función, el método pasará a llamarse `title_pt_br`, que es correcto, y, además, no genera conflictos en las vistas a la hora de comparar el locale `pt-BR` con el modificado `pt_br`. Se usará siempre el segundo. + +## 6. Añadir los parámetros ocultos para borrar traducciones + +Al formulario que se use para editar las traducciones se le deberá añadir el parámetro oculto que las marca para que se borren: + +``` +<%= hidden_field_tag "delete_translations[#{locale}]", 0 %> +``` + +También habrá que añadir el link de "Eliminar idioma", que deberá tener: + +- un id con el formato `delete-`, siendo "locale neutro" el resultado de la función `neutral_locale(locale)`. +- un atributo `data-locale` con el valor de `neutral_locale(locale)`. +- la clase `delete-language`. + +``` +<%= link_to t("admin.milestones.form.remove_language"), "#", + id: "delete-#{neutral_locale(locale)}", + class: 'delete-language', + data: { locale: neutral_locale(locale) } %> +``` + +Los estilos de CSS y el resto de clases que se le quieran añadir dependerán de la interfaz que se haya diseñado para gestionar esas traducciones (si se debe ocultar o no dependiendo del idioma seleccionado, por ejemplo). + +## 7. Añadir al `dev_seed` las traducciones del nuevo modelo + +Para que se generen cuando se restablezca la base de datos. Por ejemplo, para crear un post cuya descripción está traducida: + +``` +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 +``` \ No newline at end of file