samedi 29 décembre 2012

Internationalisation de CodeIgniter


CodeIgniter est un framework PHP open-source qui suit l'architecture MVC (Modèle-Vue-Contrôleur). Il a pour principal atout d'être plus simple et léger (4Mo tout mouillé) que Zend ou Symfony, avec une prise en main très facile. Nous allons détailler dans ce billet l'internationalisation par fichiers de langue dans la version 2.1.3 de ce framework.

Gestion de l'internationalisation


La langue par défaut est définie dans le fichier de configuration application/config/config.php
$config['language'] = 'en';
Les fichiers de langue se rangent dans le répertoire application/language/

Nous optons ici pour un code de langue à deux lettres (en, code ISO 639-1), mais nous aurions pu tout aussi bien utiliser un code à trois lettres (eng, code ISO 639-2 ou 639-3), un code à deux lettres localisé (en-ca pour l'anglais du Canada, codes langue ISO 639-1 et pays ISO 3166-1), le nom de la langue en toutes lettres (english), ou tout autre formalisme.

L'usage préconisé est de préfixer le nom du fichier de langue (_lang.php) par une unité sémantique (ici, le nom du contrôleur, soit test).

De même, afin d'éviter toute collision de clés entre les différents fichiers, il est d'usage de préfixer chaque clé par cette même unité sémantique.

system/language/en/test_lang.php
$lang['test_test'] = "Let's test";
$lang['test_my_view'] = "My view";
system/language/fr/test_lang.php
$lang['test_test'] = "Essayons";
$lang['test_my_view'] = "Ma vue";

L'appel d'une variable localisée se fait dans le contrôleur en chargeant le fichier de langue via la méthode load à laquelle on passe deux paramètres : le préfixe du fichier de langue (ici, le nom du contrôleur en minuscules) et le code de langue utilisé comme sous-répertoire du répertoire des langues (si ce second paramètre est omis, c'est la langue par défaut du fichier de configuration qui sera utilisée).

On attribue ensuite les variables contenant les chaînes du fichier de langue via la méthode line (paramétrée par la clé du tableau associatif $lang), comme autant de clés du tableau associatif $data.

Le contrôleur se présente alors ainsi :
public function view() {
    $this->lang->load('test', 'fr');

    $data['lets_test'] = $this->lang->line('test_test');
    $data['my_view'] = $this->lang->line('test_my_view');

    $this->load->view('test', $data);
}
Du côté de la vue, les variables sont directement affichables : $lets_test et $my_view.

Utilisation de paramètres dans un fichier de langue


L'approche directe consiste à insérer autant d'espaces réservés que nécessaires dans la chaîne localisée en suivant le formalisme de la fonction PHP sprintf (soit %s pour une chaîne standard).

application/language/en/test_lang.php
$lang['test_lets'] = "Let's %s now";
$lang['test_program'] = "program";
application/language/fr/test_lang.php
$lang['test_lets'] = "Allons %s maintenant";
$lang['test_program'] = "programmer";
Le contrôleur insère la sous-chaîne manquante lors de l'appel.
$data['lets_dance'] = sprintf($this->lang->line('test_lets'), $this->lang->line('test_program'));
L'affichage dans la vue donnera alors, soit Let's program now, soit Allons programmer maintenant.

Le problème se complique lorsque plusieurs sous-chaînes sont passées en argument, leur ordre pouvant être différent selon les langues employées.
L'astuce consiste alors à utiliser des paramètres numérotés via la fonction sprintf. Les variables peuvent aussi être réutilisées.

application/language/en/test_lang.php
$lang['test_there'] = "There are %1\$s in the %2\$s. I like %1\$s.";
$lang['test_monkeys'] = "monkeys";
$lang['test_banana_tree'] = "banana tree";
application/language/fr/test_lang.php
$lang['test_there'] = "Le %2\$s est plein de %1\$s. J'aime les %1\$s.";
$lang['test_monkeys'] = "singes";
$lang['test_banana_tree'] = "bananier";
Le contrôleur insère les sous-chaînes manquantes lors de l'appel dans le même ordre, quelle que soit la langue.
$data['there'] = sprintf($this->lang->line('test_there'), $this->lang->line('test_monkeys'), $this->lang->line('test_banana_tree'));
L'affichage dans la vue donnera alors, soit There are monkeys in the banana tree. I like monkeys, soit Le bananier est plein de singes. J'aime les singes.

Récapitulatif


Nous avons vu dans ce court tutoriel comment internationaliser une application réalisée avec le framework CodeIgniter : comment définir des fichiers de langue, comment les charger dans les contrôleurs, puis afficher leurs variables dans les vues, tout en gérant leur paramétrisation et le problème de l'ordre des variables.

Dans un prochain billet, nous verrons comment rendre les URLs de CodeIgniter SEO-friendly et internationalisées.

Lecture


Professional CodeIgniter


Pour aller plus loin, je vous conseille la lecture de cet ouvrage : Professional CodeIgniter, par Thomas Myer (2008, 336 pages).


CodeIgniter internationalization (en anglais)
Internacionalización de CodeIgniter (en espagnol)
Internacionalização de CodeIgniter (en portugais)

4 commentaires:

  1. Bonjour,
    Qu'est ce que ça engendre cette internationalisation?
    Ca modifie les messages d'erreur et systeme affichés par le framework, c'est ça?

    RépondreSupprimer
    Réponses
    1. Bonjour,

      Les messages d'erreur et système ne sont pas affectés par cette internationalisation. Il s'agit ici de pouvoir afficher un texte sur une page en fonction de la langue en paramètre, sans changer la vue correspondante.

      Si votre site est multilingue, les vues seront les mêmes pour toutes ses langues, ainsi que les contrôleurs (dès lors que vous gérerez ce paramètre de langue).

      Même si votre site ne comporte qu'une langue, il est utile de passer par de tels fichiers de langue pour pouvoir centraliser tous vos textes. Ainsi, vous êtes sûr d'utiliser les mêmes mots pour les mêmes concepts, et vous pouvez aussi modifier un terme sur le site en entier dans un seul fichier.

      Supprimer
  2. Bonjour,

    Est-ce qu'il faut créer un fichier langue par vue ?
    par module ?

    Merci pour vos conseils.

    RépondreSupprimer
  3. L'idéal est de créer des fichiers de langue avec la granularité la plus faible possible. Par exemple, si toutes vos vues ont des textes différents mais un en-tête commun, la partie commune sera dans son propre fichier, et chaque vue aura son fichier en plus.
    Le but ici est de limiter au mieux la duplication de texte entre les fichiers de langue pour faciliter à la fois leur utilisation et leur maintenance.

    RépondreSupprimer