Créer une application ruby on rails en plusieurs langues avec gettext
Gettext
est une bibliothèque qui permet de réaliser une application en
plusieurs langues, facilement, et en facilitant la traduction.
Dans le jargon RubyOnRails,
l'internationalisation (ou l'internationalization
en anglais), est le fait de créer une application en plusieurs
langues, gettext est justement recommandé pour cela.
Gettext a pour avantages, le fait qu'il ne
soit pas limité à ruby on rails, qu'il soit très utilisé, qu'il
existe des interfaces graphiques pour la traduction, qu'il ne
nécessite pas de base de données, qu'il soit léger, sous
licence gnu, etc…
Pour utiliser gettext avec ruby, il existe
Ruby-GetText-Package.
Il est complet, et propose un bon support pour aller avec ruby
on rails.
Pour l'installation, on peut utiliser les gems:
gem install
gettext
Il faut ensuite charger gettext dans votre application ruby on
rails.
Pour cela, il faut ajouter dans le fichier config/environment.rb les
lignes suivantes:
$KCODE =
'u'
require
'jcode'
require
'gettext/rails'
LANG = 'fr'
La constante LANG est importante, c'est
elle qui définie qu'elle sera la langue par défaut de votre
application.
Il est important de noter que l'application doit maintenant
être en utf-8, en
lisant la documentation, vous pouvez adapter les réglages pour
d'autres encodages, mais l'unicode est recommandé pour ce genre
d'utilisation.
Il faut maintenant rajouter les méthodes
rake pour la gestion des langues, ceci n'étant pas automatique.
Pour cela, il faut créer un nouveau fichier lib/tasks/gettext.rake,
contenant:
desc "Update
pot/po files."
task :updatepo
do
require
'gettext/utils'
GetText.update_pofiles("nom_de_votre_application",
Dir.glob(
"{app,lib,bin}/**/*.{rb,rhtml,rxml}"),
"nom_de_votre_application")
end
desc "Create
mo-files"
task :makemo
do
require
'gettext/utils'
GetText.create_mofiles(true, "po", "locale")
end
N'hésitez pas à remplacer le nom de votre application
Je ne détaillerais pas, mais en lisant la documentation, on
peut facilement modifier ce fichier pour l'adapter à ses
besoins.
Il faut maintenant initialiser gettext.
À placer sans le fichier app/controllers/application.rb:
init_gettext "nom_de_votre_application"
Évidemment, il s'agit du même nom que celui définie plus haut.
L'application va contenir deux nouveaux
dossiers.
Un dossier po qui contiendra les traductions en langage humain
(des fichiers en .po).
Un dossier locale qui contiendra les traductions en langage
machine (des fichiers en .mo).
Dans chacun de ces dossiers, il y aura un dossier par
traduction (fr, en, fr_FR, en_US, etc…).
Le dossier po contient aussi à sa racine un
fichier qui sert de base pour commencer de nouvelles
traductions, il ne sert jamais à l'application (il a pour
extension .pot).
Pour créer l'arborescence des fichiers en langage humain, il
faut donc utiliser la commande:
rake updatepo
Un dossier équivaut à une traduction (fr,
en, de, it, es, ja…).
Ces dossiers contiennent chacun une copie du fichier en .pot
renommé en .po
Vous pouvez maintenant commencer à intégrer les traductions
dans votre application.
À chaque fois qu'il y a du texte à utiliser
en plusieurs langues, il faut lui donner un texte
d'identification (aussi appelé clé), et utiliser la fonction
_()
<h1>Connexion
</h1>
#devient:
Une fois
les textes remplacés, la commande rake updatepo permet
d'insérer ces références automatiquement des les fichiers du
dossier po.
<h1><%= _('titre_connexion')
%></h1>
On trouvera par exemple:
#:
app/views/user/login.rhtml:17
msgid "titre_connexion"
msgstr ""
Il suffit maintenant de mettre le texte traduit pour chaque
langue, ce qui donne pour la version japonaise (contenu dans le
dossier po/ja/):
#:
app/views/user/login.rhtml:17
msgid "titre_connexion"
msgstr "
関係"
Lorsque vous affichez la page, <h1>titre_connexion</h1>,
est affiché. Pour que la traduction soit prise en compte, il
faut générer les fichiers en langage machine pour que le texte
traduit soit affiché.
rake makemo
Pour la version japonaise, ça donne:
<h1>関係</h1>
À chaque nouveau texte à traduire, après
l'avoir identifié, il faudra mettre à jour les fichiers .po
(rake updatepo).
À chaque modification d'un fichier .po, pour que les
modifications soient affichées, il faudra régénérer les
fichiers .mo (rake
makemo).
Tout ça,est très pratique, mais il manque le principal: le
choix de la langue.
before_init_gettext :set_languages
init_gettext "alternc"
def set_languages
#Règlage la langue
if !params[:lang].nil?
#Si il y a un paramètre
pour changer la langue, vérification de l'existence de la
langue
if
File.exist?(RAILS_ROOT+
'/po/'+params[
:lang]) ||
File.exist?(RAILS_ROOT+
'/po/'+params[
:lang]+'_'+params[:lang].upcase)
session[
:lang] =
params[:lang]
else
session[
:lang] =
nil
end
end
begin
#Si la langue choisie
n'existe pas, ou si c'est la première visite
if
session[:lang].nil?
break
end
#Si non, on règle
simplement la langue
set_locale
session[:lang]
rescue
#Si le navigateur envoi
des informations sur la langue
if !@request.env['HTTP_ACCEPT_LANGUAGE'].nil?
#recherche de la langue
du client
langs
= @request.env['HTTP_ACCEPT_LANGUAGE'].
gsub(/;q=[0-1]\.[0-9]/,
'').split(
',')
langs.each
do |i|
#si elle n'existe pas,
les langues secondaires sont étudiés
if
File.exist?(RAILS_ROOT+
'/po/'+i) ||
File.exist?(RAILS_ROOT+
'/po/'+i+
'_'+i.upcase)
session[
:lang] = i
break
end
end
end
#Si il n'en existe
toujours pas, la langue est celle utilisée par default, dans la
configuration de l'application
if
session[:lang].nil?
session[
:lang] = LANG
end
#Réglage final de la
langue
set_locale
session[:lang]
end
end
Cette méthode, à placer dans app/controllers/application.rb
détecte la langue du navigateur, et celles subsidiaires. Si il
y en a aucune de traduite, c'est celle définie par la constante
LANG qui est
choisie. Cette méthode permet aussi de sauvegarder la langue
d'une page à l'autre. Pour changer la langue manuellement, il
faut donner un paramètre get lang. Par exemple ?lang=en
Parfois, on a aussi besoin d'inclure des
variables dans un texte à traduire, comme le nom du serveur.
#:
app/controllers/user_controller.rb:3
msgid "user_login_page_title"
msgstr "Se connecter
au serveur: %{SERVER_NAME}"
@page_title =
_('user_login_page_title')%
{:SERVER_NAME
=>"yellowimac"}
Ce qui donne:
"Se connecter au
serveur: yellowimac"
Ceci grâce à la méthode % qui a pour paramètre un
hashage. C'est une extension de la class String, c'est à dire
que vous pouvez aussi utiliser cette méthode sur un texte qu'y
n'a rien à voir avec gettext.
"La page a
pour titre %{titre}, elle sur le serveur
%{serveur}"% {:titre =>
"Accueil",
:serveur =>
"yellowimac"}
Voilà, maintenant vous êtes près à créer des
applications parfaitement multilingues, rapidement et
facilement.
Pour aller plus loin:
- Voir la définition de gettext sur wikipedia
- Internationalisation de logiciel sur wikipedia
- HOWTO for Ruby on Rails - Ruby-GetText-Package
- Translating Rails Apps - Manuel de RubyOnRails
Le 05/07/2007 à 19:51
Intéressant, ce blog.
J'hésitais à le mettre au Ruby... Mais une question me dérange encore, certes probablement idiote, mais le Ruby n'est pas adapté qu'au web, comme PHP ou ASP ? On peut faire des applications indépendantes avec ? (une réponse par mail serait appréciable, étant donné que je n'ai pas le temps de revenir visiter en ce moment..) Merci !