Créer un site multilingue avec CodeIgniter

Version de CodeIgniter utilisé: 2.1.2

Les fonctionnalités souhaitées:

  • Affichage de la langue dans l’URL. Cela permet un meilleur référencement, avec un lien unique vers un contenu dans une langue donnée. (exemples: www.mondomaine.com/fr, www.mondomaine.com/en)
  • Détection de la langue du navigateur
  • Facilité d’évolution (ajouter une nouvelle langue)
  • Facilité d’utilisation pendant le développement

URI Language Identifier

Le vrai secret pour faire ce que l’on souhaite, est une extension de la bibliothèque Lang, disponible sur le wiki de CodeIgniter.

Cette extension permet d’afficher la langue dans l’URL et de modifier la config suivant cette langue. Si aucune langue n’est détectée, la langue par défaut est chargée.

Avec la fonctionnalité de base, on a déjà une bonne partie, mais nous n’avons toujours pas de détection de la langue du navigateur. Donc si la langue par défaut est l’anglais, qu’un utilisateur français accède à votre site sans langue spécifiée dans l’URL, il se retrouvera avec un site en anglais, alors que vous supportez aussi le français.

J’ai donc modifié cette extension afin qu’elle supporte la détection de la langue du navigateur lorsque aucune langue n’est précisée dans l’URL.

application/core/MY_lang.php

Voila, maintenant notre librairie répond parfaitement à nos attentes. Je vais maintenant vous expliquer comment la configurer, et comment l’utiliser sur votre site.

Configuration de la librairie

/application/config/config.php

$config[‘language’] représente la langue par défaut.

$config[‘language_abbr’] représente l’abréviation de la langue par défaut.

$config[‘lang_uri_abbr’] représente les langues acceptées par le site. Si vous souhaitez ajouter une nouvelle langue, c’est ici que ça se passe.

$config[‘lang_ignore’] permet de ne pas afficher la langue dans l’URL, et de seulement l’enregistrer dans un cookie. Ici cette fonctionnalité ne nous intéresse pas, donc FALSE.

application/config/routes.php

Maintenant il faut configurer les routes, puisque notre URL ressemble à ça : www.mondomaine.com/lang/controller/method/variables et ne correspond plus au modèle de fonctionnement de CodeIgniter: www.mondomaine.com/controller/method/variables.

Par contre, si vous souhaitez ajouter une nouvelle route, il faudra l’ajouter avant ces dernières et tenir compte de la langue. Exemple:

Voila maintenant tout est configuré et fonctionnel. Je vais maintenant vous comment utiliser tout cela.

Utilisation

Configuré c’est bien beau, mais comment je fais pour récupérer les bons textes suivant la langue ???

Tout se passe dans le répertoire application/language. Normalement vous avez un répertoire « english » qui est déjà créé. Il suffit de rajouter un nouveau répertoire pour chaque langue souhaitée.

Ensuite il faut créer un fichier de langue par répertoire de langue, ayant exactement le même nom et le suffixe « _lang ». Par exemple form_lang.php. Ce fichier de langue servira pour tous mes formulaires.

Ensuite le contenu de ce fichier est un simple tableau PHP.

application/language/francais/form_lang.php

application/language/english/form_lang.php

Maintenant il ne reste plus qu’à charger le bon fichier de langue dans le constructeur de votre contrôleur.

Pour l’utilisation, il suffit d’utiliser le helper présent dans l’extension de la librairie Lang:

Ensuite pour toutes les fonctions d’aide à la création d’URL (URL Helper), il faut utiliser base_url pour avoir l’URL du site (www.mondomaine.com), et site_url pour avoir l’URL avec la langue (www.mondomaine.com/fr).

Astuces

Pour les fichiers de langue en Français et autres, n’oubliez pas d’enregistrer en UTF-8 sans Bom afin d’éviter les erreurs.

Pensez à copier les fichiers de langue présents dans system/language/english vers vos nouveaux répertoires de langue afin d’avoir les erreurs affichées au moins en anglais.

60 thoughts on “Créer un site multilingue avec CodeIgniter

  1. Bonjour,

    Merci pour ce tuto très intéressant ! Je voulais vous demander, comment faire pour changer de langue dans une page (en cliquant sur un drapeau) puisque le deuxième argument du lang->load est désormais défini automatiquement ($this->config->item(‘language’) ). J’imagine qu’il faut changer la langue dans l’url, et si c’est le cas, existe-t-il un moyen simple ?

    Merci d’avance.

    • Bonjour,
      Effectivement il suffit de modifier l’url et cela sera pris en compte directement dans l’extension de la librairie. Le moyen le plus simple de faire ca est base_url(‘fr’) ou base_url(‘en’).

  2. Bonjour,
    Tout d’abord merci pour le tuto. Excactement ce que je recherchais. SUPER
    J’ai deux questions :
    – Commment garder l’url de la page en cours en ne modifiant que le segment lang ?
    – Comment faire pour garder en mémoire le choix de la langue sur tout le site ? (si je change de page) la langue par défaut est sélectionnée (dans mes liens le segment n’est pas ajouté)

    Je vous remercie par avance. 🙂

  3. Je viens de me creuser un peu la tête et ceci fonctionne :
    base_url(‘index.php/us’).$this->uri->uri_string()

    Je ne sais pas si c’est la meilleure manière mais fonctionne 🙂

    • Bonjour,
      Pour la première question, effectivement la solution que vous proposez fonctionne. Pratique pour changer directement la langue de la page courante.

      Pour la seconde question, pour que les liens de la page gardent la langue choisie, il faut utiliser la fonction site_url qui génére « www.mondomaine.com/us » et non base_url qui génère seulement « www.mondomaine.com ».

      J’espère avoir répondu à votre question.

  4. Bonjour,
    Merci pour ce tuto et cette librairie très pratique.

    Je viens juste de constater que cette ligne du code (line 47) :
    /* adjust the uri string leading slash */

    pose un problème pour la gestion du cache de CI en mode lang_ignore=true.

    le « uri_string » est modifié (avec un slash au début) du coup
    les fonctions « _write_cache » et « _display_cache » de l’output.php n’ont plus la même url
    (http://www.exemple.com//test pur la première et http://www.exemple.com/test pour la seconde)
    du coup « _display_cache » ne retrouve plus son fichier dans le dossier cache.

    cette ligne de code est-elle indispensable pour le bon fonctionnement de votre class ?
    Je viens de la commenter et cela marche parfaitement dans les 2 modes …

    • Bonjour,
      Ce n’est pas moi qui ai développé cette extension, je l’ai juste améliorée pour qu’elle puisse détecter la langue du navigateur.
      J’ai testé de mon coté de commenter cette même ligne et tout fonctionne très bien aussi.

  5. Merci pour la modification et le partage de ce script, moi qui débute avec CI je n’ai pas eu trop de mal à le mettre en place.

    J’ai cependant deux petites questions en cascades :

    1) Dans quelle mesure est-il possible de d’afficher les uri dans chaque langue respective…
    http://www.exemple.com/en/jobs
    http://www.exemple.com/fr/emplois
    …sans pour autant avoir à créer les classes contrôleurs correspondants ?

    2) Procéder ainsi aiderait-il à l’amélioration du référencement ?

    Merci par avance.

  6. Bonne idée de solution pour la première question.

    Encore une nouvelle question, comment détecter la langue en cours depuis n’importe quelle vue ?
    Ce que j’ai fait : J’ai ajouté une petite fonction à MY_Lang, à laquelle on passe en argument « fr » ou « en ». J’appelle cette fonctione depuis ma vue « menu » et son but est d’appliquer un style CSS sur la langue active.

    – – – –

    function activ_lang($langue) {
    global $LANG;
    $current = ($t = $LANG->line(‘isset’)) ? $t : ‘isset’;
    if ($langue == $current) {
    echo ‘class= »active »‘;
    }
    else {
    echo ‘class= »normal »‘;
    }
    }
    – – – –

    Au final ça marche mais je n’ai pas l’impression que ce soit la meilleure façon de faire.
    Y-a-t-il une fonction implémentée de base qui renvoie la langue active ?

    PS : Aperçu du site ici : http://www.urlgone.com/5509d8/

    • j’ai oublié de préciser, ma fonction se base sur une bidouille, j’ai défini dans chaque fichier multilangue_lang.php une ligne $lang[‘isset’]
      dans le fichier language/french/multilangue_lang.php $lang[‘isset’] = « fr »
      et dans language/english/multilangue_lang.php $lang[‘isset’] = « en »

      Je ne sais pas si je suis clair. Dans tous les cas, ne peut-on pas faire plus simple pour détecter la langue en cours ?

      • Ca ne sert a rien de créer une fonction pour connaitre la langue utilisée. Il suffit de faire ca: $this->config->item(‘language_abbr’)
        Après pour ta « bidouille », je ne comprends pas trop le but, car le bon fichier de langue se charge automatiquement suivant la langue.

        • merci pour m’avoir remis dans le droit chemin !! $this->config->item(‘language_abbr’) remplace tout le triturage d’esprit que je me suis fait…
          C’est un attribut ajouté par la class MY_Lang c’est ça ??

  7. Nouveau problème : Dès lors que je veux utiliser un model et que j’effectue une requête grâce à lui, j’obtiens l’erreur suivante :
    Unable to load the requested language file: language/francais/db_lang.php

    J’ai googlé l’erreur, personne n’a de solution j’ai l’impression.

    • Pour les deux dernières questions tout est dans le tuto.
      L’attribut tu l’as rajouté dans le fichier config.php pour que la librairie fonctionne.
      Pour l’erreur de fichier, il faut que tu copies tous les fichiers présents dans /system/language/english vers /application/language/fr.

  8. Merci Maxime, je crois que tu peux supprimer ma question du 6 février 2013, ainsi que ta réponse.
    En effet, il semble que le problème trouvait sa source en amont, vu que je n’avais pas bien configuré la BDD dans le fichier de config ‘database.php’.

  9. Bonjour,
    Merci pour ce script qui marche à merveille en local.
    Mais bizarrement, lorsque je l’ai mis sur serveur, problème… Tous les liens du site ne charge qu’une vue… J’ai beau changé l’url, c’est toujours la même vu qui est chargée…
    Sauriez-vous d’où cela peut venir ?

    Cdlt.

    • Pour ma part, cela fonctionne bien en local (sur un serveur NAS Synology) et en ligne (chez Mavenhosting) sans rien changer. C’est pas mon fort mais, je pense qu’il faut que tu regarde du côté du .htacces et/ou des routes CI.

    • Essaye ce .htaccess

      RewriteEngine on
      RewriteBase /
      RewriteRule ^(application|system) index.php/$1 [L]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^([a-z]{2})/(.*)$ /index.php?/$2/$1 [QSA,L]

      Tu devrais pouvoir protéger tes dossiers systems et prendre en charge le module de notre ami Maxime. Merci Maxime pour ton travail !

  10. Bonjour,

    En utilisant ce code, les POST ajax jquery avec l’url du site : http://monsite/controleur/fonction
    ne fonctionnent plus

    Des idées ?

  11. Bonjour,
    Merci beaucoup pour ce script.
    Une question, comment fait – on pour changer manuellement la langue sans passer par une rediréction du genre http://monsite.fr/en.
    En effet, pour ne pas changer l’url, on a proccéder à la récupération de la langue par la fonction get_cookie(‘user_lang’) et elle marche bien, cependant en modifiant la langue avec set_cookie(‘user_lang’,’fr’) par exemple, ça ne semble pas marcher.
    Merci d’avance.

    • La démarche me paraît correcte. As-tu vérifié la valeur du cookie après modification (firebug, ou autre) ? Peut-être qu’il faut supprimer l’ancien et en recréer un avec la nouvelle valeur.

      • On a déja éssayer de supprimer la cookie, mais ça n’a pas marché: La valeur est réstée la même.

      • Bonjour,
        Merci Maxime pour ce tuto qui nous aide bcp,
        Cette solution de Javascript est marche bien mais juste pour les sites qui sont hébergés par contre en local fait un problème, y a des solution pour faire un cas général, soit d’utiliser « $this->lang->lang(); » soit de mettre un prame de lang  » $lang[‘get_lang’] = ‘fr’;  » et l’utiliser dans le code « echo lang(‘get_lang’) »

        Merci,

  12. Bonjour chers frères codeurs ( si je puis me permettre ).

    Tout comme vous je me suis confronté à ce problème.
    Ce tuto est très bien et merci. Cependant, n’étant pas habituer à ce frame work, certains passage m’étaient abscons sur l’appel et l’emploi, etc.
    Je vous fais suivre ce lien:

    https://github.com/EllisLab/CodeIgniter/wiki/CodeIgniter-2.1-internationalization-i18n

    ce tuto m’a pleinement satisfait et à répondu à l’ensemble des questions poser ici.

    A savoir,
    je détecte la lang du navigateur,
    je peux switcher d’une lang à une autre.
    je créée mes librairie de langue à volonté.
    et j’ai une langue par défaut.

    très facile d’usage une fois installé.
    les url ce présente ainsi:
    http://www.monexemple.com/fr/home

    pour récuperer le fr ( ou ‘en’ selon le cas )
    echo $this->lang();

    sur les petits drapeaux de choix de langues:
    <a href="lang->switch_uri(‘fr’); ?> » title= »Français » id= »fr » >fr.

    et dans le menu de navigation ( qui change selon la langue choisie )
    lang->lang().’/mon_controller_page’ ?>’>lang->line(‘texte_traduit_dans_un_menu_lang’); ?>

    voilà, je souhaitais le partager puisque j’ai apprécié vos pertinences.
    merci
    🙂

  13. Bonjour,

    J’ai un souci de boucle de redirection et ce uniquement sur la langue FR.
    une adresse http://monsite.fr/en/ marche nickel mais pas http://monsite.fr/fr qui me fait cette fameuse boucle.

    Une idée ?

  14. Bonjour,
    merci pour cette modification.
    ma question est : comment faire pour le route de sitemap.xml sans les mondomaine.com/sitemap.xml au lieu de mondomaine.com/fr/sitemap.xml

    • Rien de spécial à faire, l’accès au fichier se fait directement. Comme pour mondomaine.com/robots.txt.

      • dans mon cas je génère le sitemap.xml avec codeigniter home/sitemapXML, j’ai créer cette entrée dans le fichier routes : $route[‘sitemap.xml’] = ‘home/sitemapXML’;
        mais ça marche pas page introuvable.

      • J’ai trouve la solution :
        Ajouter dans la classe MY_Lang
        $uri_abbr = $URI->segment(1);
        if($uri_abbr == ‘sitemap.xml’)
        return;

        ceci ignore le routage de langue pour sitemap.xml

  15. J’ai le même souci que Jérome plus haut : une fois en ligne (ovh mutualisé) le systeme ne fonctionne plus. j’ai essayé de mettre le .htaccess comme précisé,etc…
    j’ai l’impression que la librairie ne se charge pas.
    Quelqu’un a déjà eu et résolu ce souci ?

    • Solution :
      Retirer le fichier My_lang.php de core et le mettre dans le répertoire application/librairies/ et ensuite mettre le chargement de cette librairie dans le fichier autoload.

      Ca marche mais je ne comprend pas pourquoi cela ne marche pas dans la situation de base. j’aimerai bien comprendre…

    • Si le serveur est Linux il faut renommer le fichier a la place de MY_lang.php mettre MY_Lang.php, car le systeme est sensible a la casse.

  16. Salut Maxime,
    Merci pour ce tuto bien pratique.
    Cependant cela ne semble pas fonctionner pour moi.
    J’ai suivi le tuto à la lettre mais lorsque je change la langue dans l’url cela ne change rien.
    J’ai fait afficher la langue active avec $this->config->item(‘language_abbr’) et c’est effectivement la langue par défaut qui s’affiche à chaque fois, peut importe la langue que je met dans l’url.
    Une idée d’où cela peut venir?

  17. Ca marche! Je ne sais pas ce qui n’allait pas mais après plusieurs bidouillages et après avoir vidé le cache de mon navigateur ça fonctionne.
    Ne me demande pas ce qui n’allait pas je n’en sais rien car au final j’ai remis la même configuration que j’avais avant.
    Peut-être était-ce simplement le fait de vider le cache?

    Merci encore

  18. Bonjour,
    Je veux savoir comment récupérer la valeur de cookie pour l’utiliser dans le model comme ceci:
    if ($cookie= »_fr »){$table = ‘an_user_fr’;
    }else{$table = ‘an_user_en’;}

  19. Merci pour ce tuto qui me sauve la vie, c’est exactement ce dont j’avais besoin par contre je n’arrive pas le mettre en place comme il faut !

    Je pense avoir correctement suivi le tuto, mais maintenant toutes mes requétes post ne passe plus a cause de la redirection de la librarie !

    Serait-ce un probléme lier a mes routes ?
    Ou bien, est-ce que je dois changer toutes les urls du site (formulaire, lien etc…) pour y ajouter la langue ?

    Voici à quoi ressemble mon fichier route :

    $route[‘default_controller’] = « home »;
    $route[‘404_override’] = ‘error404’;
    $route[‘\w{2}/404_override’] = ‘error404’;
    $route[‘accueil’] = « home/index »;
    $route[‘\w{2}/accueil’] = « home/index »;
    $route[‘espace-membre/mon-profil/supprimer-ci/([0-9]+)’] = « espace-member/myprofil/del_attach_validation/$1 »;
    $route[‘\w{2}/espace-membre/mon-profil/supprimer-ci/([0-9]+)’] = « espace-member/myprofil/del_attach_validation/$1 »;
    $route[‘(\w{2})/(.*)’] = ‘$2’;
    $route[‘(\w{2})’] = $route[‘default_controller’];

    y a t’il des erreurs ?

    Merci d’avance pour vos réponses !

  20. Existe t-il une alternative pour la version 1.7.2, car cela ne fonctionne pas correctement dessus ça m’as déréglé le fonctionnement natif de CI sur le $this->uri->segments ! Bizarre non ?! il ne retourne plus les bon segment d url !

  21. Il est joli ce tuto. Merci

  22. Salut,

    Merci pour ce bon tuto.
    J’ai un problème néanmoins… mes CSS et JS ne se chargent plus.

    J’utilise un helper pour construire l’url de mes assets.
    Par exemple pour les CSS :

    function css_url($nom, $version = null)
    {
    if($version == null){
    return base_url() . ‘assets/css/’ . $nom . ‘.css’;
    }else{
    return base_url() . ‘assets/css/’ . $nom . ‘.css?v=’.$version;
    }

    }

    Du coup, l’URL d’un fichier CSS devient :
    http://localhost/nom_site/fr/assets/css/style.css
    au lieu de :
    http://localhost/nom_site/assets/css/style.css

    Que faut-il que je corrige pour récupérer mes CSS ?
    Merci bcp.

    Vincent.

    • Bonjour,

      Pour info, j’ai trouvé sur internet dans mon cas. J’ai pu régler ce problème en enlevant un « ? » dans mon .htaccess. Je n’explique pas pourquoi, mais c’était suggéré et ca à fonctionné.

      merci pour cet article.

  23. Merci pour le super tutoriel,
    cependant j’ai un sérieux problème, lorsque je met en place le script je remarque que mes POST sont vide. c’est à dire que si j’ai un formulaire de connexion cela ne passe plus car lorsque je valide pour me connecter les champs pseudo et password du POST sont vides par contre je remplis les champs.. je comprend pas d’où vient le problème . quelqu’un pour m’aider ?
    merci d’avance .

  24. Probablement une bête question mais dans la vue, comment retourne-t-on l’abréviation de langue en question ?

    Histoire de faire bien dans :

    html lang= »malangue »

  25. Bonjour et merci bcp pour ce tuto.

    Je ne suis pas développeur PHP mais j’ai pu régler qq problèmes tout de même!

    Il me reste une question à traiter. Mon site possède deux langues FR et EN dont le choix se fait automatiquement pour l’instant mais j’aimerais qu’il soit possible de choisir en cliquant par ex sur un drapeau situer au niveau du menu.

    Pourriez-vous m’aider et me dire à quel niveau du framework CI je pourrais faire ça ??
    Merci bcp.

  26. Bonjour,
    j’ai un problème; lorsque je veux utiliser une librairie type form_validation ou email en AJAX php m’affiche une erreur :

    Call to a member function load() on a non-object in C:\UwAmp\www\Site-SocietaOnorata\system\libraries\Email.php on line 1973

    (en gros; dans la lib Email il essai de loader un fichier de langue avec l’objet Lang de base et non MY_Lang… enfin je pense… HELP ?)

    Sauriez vous me dire ce que j’ai mal fais ? :s

  27. Salut, super tuto j’apprecie énormément. Cependant, je voulais faire quelques tests unitaires et je me suis rendu compte que ça ne marchait pas lorsque je mettais un système multilingue. Est ce que c’est normal ou que je m’y suis mal pris ? Aurais-tu déjà rencontré ce problème ? Tous mes tests unitaires me renvoient toujours 0.

  28. Bonjour,

    J’ai essayé le script et il marche parfaitement mais j’aimerai utiliser les sessions plutôt que les cookies, cependant je ne trouve pas comment utiliser les sessions depuis le script, pourriez-vous m’aider sur ce point ?

    Merci 🙂

  29. Baye demba diack

    rien ne marchais avec moi

    il a fallut que j’ajoute la fonction suivante dans la classe uri.php(system\core\)

    //bdd
    public function _reindex_segments()
    {
    array_unshift($this->segments, NULL);
    array_unshift($this->rsegments, NULL);
    unset($this->segments[0]);
    unset($this->rsegments[0]);
    }

    pour que les choses marches

  30. Baye demba diack

    urgent, urgent

    Bonjour, en local tout marche avec moi sans problème

    mais une fois que je déploie mon site en ligne il me signale une erreur et plus rien ne marche

    Fatal error: Call to undefined function t() in /home/e…/application/views/index.php on line 106

  31. Baye demba diack

    En fait je viens de régler le bug!!!
    vous savez Linux ne tolère pas de différence sur la casse du nom des fichiers.

    en réalité le fichier doit s’appeler application/core/MY_Lang.php et non application/core/MY_lang.php

    différence en L et l.

  32. Est-il possible de définir dynamiquement la langue par défaut ? J’utilise le code fourni dans cet article, et qui fonctionne à merveille, pour un projet « multi-sites », dont certains ont une langue spécifique par défaut, et dont celle-ci est définie dans une DB. Cela veut dire que je dois attribuer dynamiquement une valeur au paramètre « $config[‘language_abbr’] = « fr »; ». Une idée ? Merci d’avance 🙂

  33. Bonjour
    Je vous savoir comment appeler le fichier MY_Lang.php

Laisser un commentaire