26
Oct/09
0

Internationalisation des vues

Moteur de transformation

L’application est bien évidemment internationalisée et donc disponible en plusieurs langues.

Le principe est le suivant :

  • On ne travaille que sur un seul modèle de vue
  • Tous les textes sont traduits dans un fichier de propriétés
  • Les vues sont uniquement statiques, pas de traduction à la volée

Le premier point est d’utiliser un mécanisme permettant de traduire les clés des fichiers modèles en traductions. Il est possible de définir son propre mécanisme de traduction assez simplement… cependant, ici, il semble plus intéressant de se reposer sur l’API fournie par la dernière version de Rails, qui est disponible en tant que gem et utilisable de façon autonome.

Pour cela, on installe le composant :

sudo gem install i18n

On ajoute alors la dépendance dans le fichier Rakefile.rb, et on configure le système :

require "i18n"
 
I18n.load_path << Dir[ File.join(ROOT, 'support', 'locales', '**', '*.yml') ]

Les fichiers de traduction seront donc stockés dans le répertoire support/locales (ou tout sous-répertoire) et seront nommés par la langue, par exemple en.yml ou fr.yml. Par défaut, le code pays EN est utilisé.

Exemple de stockage :

- support/
  |- locales/
  |    |- en.yml
  |    |- fr.yml

Exemple de fichier de traduction en.yml :

en:
  signin: Sign in

On peut alors traduire le fichier de cette façon :

%body
  #header.fixed
    #ids
      %a#signin{ 'data-event' => "login:start", :href => "/login.html" }=I18n.t 'signin'

Pour plus de facilités, on redéfini la méthode de traduction.

Pour cela, on crée une classe d’aide qui sera ensuite utilisée par le moteur HAML :

class ViewHelper
  def t(key)
    I18n.t key
  end
end
 
.. dans la tâche de transformation
  puts "Creating view #{target}"
  #final.puts Haml::Engine.new(File.read(src), :format => :html5).render
  final.puts Haml::Engine.new(File.read(src), :format => :html5).render(ViewHelper.new)

Le moteur de rendu prend donc en paramètre une instance de notre classe et rend donc visible les méthodes de la classe aux fichiers modèles. Le code des modèles est un peu simplifié :

%body
  #header.fixed
    #ids
      %a#signin{ 'data-event' => "login:start", :href => "/login.html" }=t 'signin'

Vu la fréquence d’utilisation, c’est indispensable… et on suit le même mécanisme que Rails ce faisant.

processus

Gestion des valeurs par défaut

Si une clé n’existe pas, on se retrouve avec le message suivant :

translation missing: en, Sign_in

Si on lance la traduction pour une autre langue, on obtient le même message.

On va surcharger notre méthode de traduction afin de palier le comportement par défaut du module i18n. On veut que dans tous les cas, une traduction s’affiche. Pour cela, on procède ainsi :

  • si la clé est traduite, on renvoi la traduction
  • sinon on essaie de traduire dans la langue par défaut, en donnant une valeur par défaut au cas où la clé n’est pas traduite.
  • la valeur par défaut est la clé (moyennant quelques transformations)

Ainsi, on peut écrire le code suivant :

%body
  #header.fixed
    #ids
      %a#signin{ 'data-event' => "login:start", :href => "/login.html" }=t 'Sign_in'

Si aucun fichier de traduction n’est présent, et que l’on essaie de traduire en français, voilà ce qu’il se passe :

  • la clé française n’est pas trouvée
  • on essaie en anglais
  • la clé n’est pas trouvée
  • on affiche la valeur par défaut
  • la valeur par défaut est le nom de la clé dont les ‘_’ sont remplacé par des ’ ‘.

Donc on obtient au final la bonne valeur par défaut Sign in sans avoir rien écrit dans un fichier de traduction. Ce qui amène à quelques saisies superflues en moins

Globalement : traduction locale > traduction par défaut > valeur de la clé

Build

On modifie le script de build car maintenant chaque fichier modèle donne lieu à plusieurs fichiers HTML :

LANGUAGES = %w(en fr)
 
def render(src, target)
  puts "Creating view #{target}"
  final = File.new(target, "w+");
  final.puts Haml::Engine.new(File.read(src), :format => :html5).render(ViewHelper.new)
  final.close
end
 
haml = FileList["#{ROOT}/priv/templates/**/*.haml"].map do |src|
  LANGUAGES.each do |locale|
    src.gsub("/templates/views/", "/www/").gsub(".haml", "_#{locale}.html").tap do |target|
      file locale => src do
        I18n.locale = locale
        render src, target
        exec "create default page", "ln -s #{target} #{target.gsub('_en', '')}" if locale == 'en'
      end
    end
  end
end

Chaque fichier de langue sera recréé séparément si nécessaire. Enfin, on ajoute un lien permettant de simuler facilement la langue par défaut (codé de façon un peu naze mais ce n’est pas grave sur cette phase).

Filed under: build, i18n
Comments (0) Trackbacks (0)

No comments yet.

Leave a comment

No trackbacks yet.