Ruby on Rails
I18n - Internationalisation
Recherche…
Syntaxe
- I18n.t ("clé")
- I18n.translate ("key") # équivalent à
I18n.t("key")
- I18n.t ("clé", compte: 4)
- I18n.t ("key", param1: "Quelque chose", param2: "Else")
- I18n.t ("doesnt_exist", par défaut: "key") # spécifier un défaut si la clé est manquante
- I18n.locale # =>: en
- I18n.locale =: en
- I18n.default_locale # =>: en
- I18n.default_locale =: en
- t (". key") # identique à
I18n.t("key")
, mais à la portée de l'action / du modèle appelé
Utiliser I18n dans les vues
En supposant que vous avez ce fichier de paramètres régionaux YAML:
# config/locales/en.yml
en:
header:
title: "My header title"
et vous voulez afficher votre chaîne de titre, vous pouvez le faire
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
I18n avec des arguments
Vous pouvez passer des paramètres à la méthode I18n t
:
# Example config/locales/en.yml
en:
page:
users: "%{users_count} users currently online"
# In models, controller, etc...
I18n.t('page.users', users_count: 12)
# In views
# ERB
<%= t('page.users', users_count: 12) %>
#SLIM
= t('page.users', users_count: 12)
# Shortcut in views - DRY!
# Use only the dot notation
# Important: Consider you have the following controller and view page#users
# ERB Example app/views/page/users.html.erb
<%= t('.users', users_count: 12) %>
Et obtenez la sortie suivante:
"12 users currently online"
Pluralisation
Vous pouvez laisser I18n gérer la pluralisation pour vous, utilisez simplement l'argument count
.
Vous devez configurer votre fichier de paramètres régionaux comme ceci:
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
Et puis, utilisez la clé que vous venez de créer en transmettant l'argument count
à l'assistant I18n.t
:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
Définir la localisation via les requêtes
Dans la plupart des cas, vous souhaiterez peut-être définir les I18n
régionaux I18n
. Vous pouvez définir les paramètres régionaux de la session en cours, de l'utilisateur actuel ou d'un paramètre d'URL. Cela est facilement réalisable en implémentant une action before_action
dans l'un de vos contrôleurs ou dans ApplicationController
dans tous vos contrôleurs.
class ApplicationController < ActionController::Base
before_action :set_locale
protected
def set_locale
# Remove inappropriate/unnecessary ones
I18n.locale = params[:locale] || # Request parameter
session[:locale] || # Current session
(current_user.preferred_locale if user_signed_in?) || # Model saved configuration
extract_locale_from_accept_language_header || # Language header - browser config
I18n.default_locale # Set in your config files, english by super-default
end
# Extract language from request header
def extract_locale_from_accept_language_header
if request.env['HTTP_ACCEPT_LANGUAGE']
lg = request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first.to_sym
lg.in?([:en, YOUR_AVAILABLE_LANGUAGES]) ? lg : nil
end
end
Basé sur URL
Le locale
régional pourrait provenir d'une URL comme celle-ci
http://yourapplication.com/products?locale=en
Ou
http://yourapplication.com/en/products
Pour atteindre ce dernier, vous devez modifier vos routes
en ajoutant une scope
:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
Ce faisant, en visitant http://yourapplication.com/en/products
, vous définissez vos paramètres régionaux sur :en
. Au lieu de cela, la visite de http://yourapplication.com/fr/products
le définira comme http://yourapplication.com/fr/products
:fr
. De plus, vous ne recevrez pas d'erreur de routage en cas d'absence du :locale
, car la visite de http://yourapplication.com/products
chargera les paramètres régionaux I18n par défaut.
Basé sur la session ou basé sur la persistance
Cela suppose que l'utilisateur peut cliquer sur un indicateur de bouton / langue pour changer de langue. L'action peut être acheminée vers un contrôleur qui définit la session sur la langue en cours (et éventuellement persister les modifications apportées à une base de données si l'utilisateur est connecté).
class SetLanguageController < ApplicationController
skip_before_filter :authenticate_user!
after_action :set_preferred_locale
# Generic version to handle a large list of languages
def change_locale
I18n.locale = sanitize_language_param
set_session_and_redirect
end
Vous devez définir sanitize_language_param avec votre liste de langues disponibles et éventuellement gérer les erreurs si la langue n'existe pas.
Si vous avez très peu de langues, il peut être utile de les définir comme ceci:
def fr
I18n.locale = :fr
set_session_and_redirect
end
def en
I18n.locale = :en
set_session_and_redirect
end
private
def set_session_and_redirect
session[:locale] = I18n.locale
redirect_to :back
end
def set_preferred_locale
if user_signed_in?
current_user.preferred_locale = I18n.locale.to_s
current_user.save if current_user.changed?
end
end
end
Note: n'oubliez pas d'ajouter des routes à vos actions change_language
Paramètres régionaux par défaut
N'oubliez pas que vous devez définir les paramètres régionaux par défaut de votre application. Vous pouvez le faire soit en le config/application.rb
dans config/application.rb
:
config.i18n.default_locale = :de
ou en créant un initialiseur dans le dossier config/initializers
:
# config/initializers/locale.rb
I18n.default_locale = :it
Obtenir les paramètres régionaux à partir d'une requête HTTP
Parfois, il peut être utile de définir les paramètres régionaux de votre application en fonction de l'adresse IP de la requête. Vous pouvez facilement y parvenir en utilisant Geocoder
. Parmi les nombreuses fonctions de Geocoder
, il peut également indiquer l' location
d'une request
.
Tout d'abord, ajoutez Geocoder
à votre Gemfile
# Gemfile
gem 'geocoder'
Geocoder
ajoute des méthodes de location
et safe_location
à l'objet Rack::Request
standard afin que vous puissiez facilement rechercher l'emplacement de toute requête HTTP par adresse IP. Vous pouvez utiliser cette méthode dans une action before_action
dans votre ApplicationController
:
class ApplicationController < ActionController::Base
before_action :set_locale_from_request
def set_locale_from_request
country_code = request.location.data["country_code"] #=> "US"
country_sym = country_code.underscore.to_sym #=> :us
# If request locale is available use it, otherwise use I18n default locale
if I18n.available_locales.include? country_sym
I18n.locale = country_sym
end
end
Attention, cela ne fonctionnera pas dans test
environnements de development
et de test
, car des éléments tels que 0.0.0.0
et localhost
sont des adresses IP Internet valides.
Limitations et alternatives
Geocoder
est très puissant et flexible, mais doit être configuré pour fonctionner avec un service de géocodage (voir plus de détails ); beaucoup d'entre eux limitent l'utilisation. Il convient également de garder à l’esprit que l’appel à un service externe à chaque demande peut avoir un impact sur les performances.
Pour y remédier, il peut également être intéressant de considérer:
1. Une solution hors ligne
L'utilisation d'un joyau comme GeoIP
(voir ici ) permet d'effectuer des recherches sur un fichier de données local. Il peut y avoir un compromis en termes de précision, car ces fichiers de données doivent être tenus à jour.
2. Utilisez CloudFlare
Les pages servies via CloudFlare peuvent être géocodées de manière transparente, le code de pays étant ajouté à l'en-tête ( HTTP_CF_IPCOUNTRY
). Plus de détails peuvent être trouvés ici .
Traduction des attributs du modèle ActiveRecord
globalize
gem est une excellente solution pour ajouter des traductions à vos modèles ActiveRecord
. Vous pouvez l'installer en ajoutant ceci à votre Gemfile
:
gem 'globalize', '~> 5.0.0'
Si vous utilisez Rails 5
vous devrez également ajouter activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Les traductions de modèles vous permettent de traduire les valeurs d'attributs de vos modèles, par exemple:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
Après avoir défini les attributs de modèle à traduire, vous devez créer une table de traduction via une migration. globalize
fournit create_translation_table!
et drop_translation_table!
.
Pour cette migration, vous devez utiliser up
et down
, et non pas change
. De plus, pour réussir cette migration, vous devez d'abord définir les attributs traduits dans votre modèle, comme indiqué ci-dessus. Voici une migration correcte du modèle Post
précédent:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
Vous pouvez également passer des options pour des options spécifiques, telles que:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string,
text: { type: :text, null: false, default: "Default text" }
end
def down
Post.drop_translation_table!
end
end
Si vous avez déjà des données existantes dans vos colonnes de traduction requises, vous pouvez facilement les migrer vers la table de traductions, en ajustant votre migration:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
Assurez-vous de supprimer les colonnes traduites de la table parente après la migration sécurisée de toutes vos données. Pour supprimer automatiquement les colonnes traduites de la table parent après la migration des données, ajoutez l'option remove_source_columns
à la migration:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true,
remove_source_columns: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
Vous pouvez également ajouter de nouveaux champs à une table de traductions créée précédemment:
class Post < ActiveRecord::Base
# Remember to add your attribute here too.
translates :title, :text, :author
end
class AddAuthorToPost < ActiveRecord::Migration
def up
Post.add_translation_fields! author: :text
end
def down
remove_column :post_translations, :author
end
end
Utiliser I18n avec des balises et des symboles HTML
# config/locales/en.yml
en:
stackoverflow:
header:
title_html: "Use <strong>I18n</strong> with Tags & Symbols"
Notez l'ajout de _html
supplémentaire après le title
du nom.
Et dans les vues,
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>