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

<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
* Language Identifier
* 
* Adds a language identifier prefix to all site_url links
* 
* @copyright		Copyright (c) 2011 Wiredesignz
* @version			0.30
* Modified by 		Maxime CHAILLOU
* @add				Language's browser detection
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
class MY_Lang extends CI_Lang
{
    function __construct() {

        global $URI, $CFG, $IN;

        $config =& $CFG->config;

        $index_page    = $config['index_page'];
        $lang_ignore   = $config['lang_ignore'];
        $default_abbr  = $config['language_abbr'];
        $lang_uri_abbr = $config['lang_uri_abbr'];

        /* get the language abbreviation from uri */
        $uri_abbr = $URI->segment(1);

        /* adjust the uri string leading slash */
        $URI->uri_string = preg_replace("|^\\/?|", '/', $URI->uri_string);

        if ($lang_ignore) {

            if (isset($lang_uri_abbr[$uri_abbr])) {

                /* set the language_abbreviation cookie */
                $IN->set_cookie('user_lang', $uri_abbr, $config['sess_expiration']);

            } else {

                /* get the language_abbreviation from cookie */
                $lang_abbr = $IN->cookie($config['cookie_prefix'].'user_lang');

            }

            if (strlen($uri_abbr) == 2) {

                /* reset the uri identifier */
                $index_page .= empty($index_page) ? '' : '/';

                /* remove the invalid abbreviation */
                $URI->uri_string = preg_replace("|^\\/?$uri_abbr\\/?|", '', $URI->uri_string);

                /* redirect */
                header('Location: '.$config['base_url'].$index_page.$URI->uri_string);
                exit;
            }

        } else {

            /* set the language abbreviation */
            $lang_abbr = $uri_abbr;
        }

        /* check validity against config array */
        if (isset($lang_uri_abbr[$lang_abbr])) {

           /* reset uri segments and uri string */
           $URI->_reindex_segments(array_shift($URI->segments));
           $URI->uri_string = preg_replace("|^\\/?$lang_abbr|", '', $URI->uri_string);

           /* set config language values to match the user language */
           $config['language'] = $lang_uri_abbr[$lang_abbr];
           $config['language_abbr'] = $lang_abbr;

           /* if abbreviation is not ignored */
           if ( ! $lang_ignore) {

                   /* check and set the uri identifier */
                   $index_page .= empty($index_page) ? $lang_abbr : "/$lang_abbr";

                /* reset the index_page value */
                $config['index_page'] = $index_page;
           }

           /* set the language_abbreviation cookie */               
           $IN->set_cookie('user_lang', $lang_abbr, $config['sess_expiration']);

        } else {

            /* if abbreviation is not ignored */   
            if ( ! $lang_ignore) {                   

				/* Check the browser's language */
				$lang_browser = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
				if (isset($lang_uri_abbr[$lang_browser])) {
					$index_page .= empty($index_page) ? $lang_browser : "/$lang_browser";
				}
				else {
					/* check and set the uri identifier to the default value */
					$index_page .= empty($index_page) ? $default_abbr : "/$default_abbr";
				}

                if (strlen($lang_abbr) == 2) {

                    /* remove invalid abbreviation */
                    $URI->uri_string = preg_replace("|^\\/?$lang_abbr|", '', $URI->uri_string);
                }

                /* redirect */
                header('Location: '.$config['base_url'].$index_page.$URI->uri_string);
                exit;
            }

            /* set the language_abbreviation cookie */                
            $IN->set_cookie('user_lang', $default_abbr, $config['sess_expiration']);
        }

        log_message('debug', "Language_Identifier Class Initialized");
    }
}

/* translate helper */
function t($line) {
    global $LANG;
    return ($t = $LANG->line($line)) ? $t : $line;
}

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'] = "english";

/* default language abbreviation */
$config['language_abbr'] = "en";

/* set available language abbreviations */
$config['lang_uri_abbr'] = array("en" => "english", "fr" => "francais");

/* hide the language segment (use cookie) */
$config['lang_ignore'] = FALSE;

$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.

//route example: http://domain.tld/en/controller => http://domain.tld/controller
$route['(\\w{2})/(.*)'] = '$2';
$route['(\\w{2})'] = $route['default_controller'];

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

$route['\\w{2}/article/(:num)'] = 'article/afficher/$1';

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

$lang['form_username']			= "Nom d'utilisateur";
$lang['form_password']			= "Mot de passe";
$lang['form_passconf']			= "Confirmer le mot de passe";
$lang['form_email']     		= "Email";
$lang['form_create']			= "Créer";
$lang['form_save']			    = "Enregistrer";

application/language/english/form_lang.php

$lang['form_username']			= "Username";
$lang['form_password']			= "Password";
$lang['form_passconf']			= "Confirm your password";
$lang['form_email']     		= "Email";
$lang['form_create']			= "Create";
$lang['form_save']			    = "Save";

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

$this->lang->load('form', $this->config->item('language'));

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

echo t('form_username');

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.

Vus : 3112
Publié par Maxime CHAILLOU : 11