Application multilingue avec CakePHP 1.3

Très souvent on crée un site avec plusieurs langues et l’idéal c’est d’être le plus méthodique possible. Je vais reprendre le tutorial de « Pierre-Emmanuel Fringant – Un site multilingue avec CakePHP » avec des adaptations de ma part.

Télécharger le pack complet

1) Connexion à la base de donnée

Se connecter à la base de donnée en UTF8 dans le fichier « app/config/database.php »

var $default = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'root',
'password' => '',
'database' => 'cakephp-tuto-langues',
'prefix' => '',
'encoding' => 'utf8' // <----
);

2) Mettre le charset meta en UTF8

Dans votre fichier de layout « /layout/default.ctp » ajoutez la balise suivante dans le header.

<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>

3) Ajouter le fichier de la gestion des langues dans le boostrap

Créez un fichier langues.php dans  « app/config/langues.php ». Ici vous n’avez pas vraiment besoin de vous préoccuper du contenu, il faut juste savoir que vous pouvez ajouter différentes combinaisons de langues pour accepter X autres nouvelles langues. On pourrait donc définir ce fichier avec toutes les langues imaginables.

<?php
// Langues acceptées
$langues = array(
'fr' => 'fre',
'en' => 'eng',
'de' => 'deu',
'it' => 'ita'
);

// Français par défaut
$langue_code = 'fr';
$langue = 'fre';

// Analyse de l'URL
if(!empty($_GET['url']))
{
if(strpos($_GET['url'], '/') !== false)
{
$langue_url = substr($_GET['url'], 0, strpos($_GET['url'], '/'));
}
else
{
$langue_url = $_GET['url'];
}

// Code langue accepté ?
if(isset($langues[$langue_url]))
{
$langue_code = $langue_url;
$langue = $langues[$langue_code];

// On enlève le code langue et le slash au début de l'URL
// avant qu'elle ne soit transmise au Router
if(strlen($_GET['url']) > strlen($langue_url))
{
$_GET['url'] = substr($_GET['url'], strlen($langue_url));
}else{
$_GET['url'] = '/';
}
}
}

Configure::write('Config.langues',$langues);
Configure::write('Config.language',$langue); // Config.language => nom var en anglais obligatoire pour fonctionnement de Cake
Configure::write('Config.langue_code',$langue_code);

?>

Ensuite dans le fichier boostrap.php « app/config/bootstrap.php » on inclut le fichier « langues.php ».

// Gestion des langues
include_once(dirname(__FILE__).'/langues.php');

3) Le helper multilingue pour les liens

On crée un helper i18n qui sera utilisé pour rendre les liens qui sont par défaut genre : /livres/index/ en /fr/livres/index/ tous les liens utiliseront à présent ce Helper, afin d’avoir toujours le préfixe de la langue devant.
Créez un fichier « i18n.php » dans « view/helpers/i18n.php »

<?php
class I18nHelper extends HtmlHelper
{
function url($url = null, $full = false)
{
return '/'.Configure::read('Config.langue_code').parent::url($url, $full);
}

function link($title, $url = null, $htmlAttributes = array(), $confirmMessage = false, $escapeTitle = true)
{
return parent::link($title, $url, $htmlAttributes, $confirmMessage, $escapeTitle);
}
}
?>

Dans le fichier « app_controller.php » dans « app/app_controller.php » on fait appel au helper afin que toute l’application puisse l’utiliser.

<?php
class AppController extends Controller {
var $helpers = array('I18n','Session');
}
?>

4) Gestion des langues avec modèle / controller / database / i18n

Le but est à présent de pouvoir gérer les langues de manières dynamique pour cela on crée une table de langues dans notre base de donnée avec le script suivant.

CREATE TABLE IF NOT EXISTS `langues` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`langue_code` varchar(3) NOT NULL,
`langue_iso` varchar(3) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

--
-- Contenu de la table `langues`
--

INSERT INTO `langues` (`id`, `langue_code`, `langue_iso`, `created`, `modified`) VALUES
(1, 'fr', 'fre', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2, 'de', 'deu', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(3, 'en', 'eng', '0000-00-00 00:00:00', '0000-00-00 00:00:00');

On crée aussi une table i18 afin de gérer les traductions pour votre application, mais dans notre cas cela servira déjà à stocker le nom des différentes langues. Imaginons quand l’utilisateur est en langue « Allemand » le texte affiché sera « Deutch », bon dans notre cas j’ai mis « Allemand deu », mais je pense que vous avez compris le principe.

CREATE TABLE IF NOT EXISTS `i18n` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`locale` varchar(3) NOT NULL,
`model` varchar(200) NOT NULL,
`foreign_key` int(11) NOT NULL,
`field` varchar(200) NOT NULL,
`content` text NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Contenu de la table `i18n`
--

INSERT INTO `i18n` (`id`, `locale`, `model`, `foreign_key`, `field`, `content`, `created`, `modified`) VALUES
(10, 'fre', 'Langue', 1, 'description', 'Français', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(11, 'deu', 'Langue', 1, 'description', 'Français deu', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(12, 'eng', 'Langue', 1, 'description', 'Français eng', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(13, 'fre', 'Langue', 2, 'description', 'Allemand', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(14, 'deu', 'Langue', 2, 'description', 'Allemand deu', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(15, 'eng', 'Langue', 2, 'description', 'Allemand eng', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(16, 'fre', 'Langue', 3, 'description', 'Anglais', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(17, 'deu', 'Langue', 3, 'description', 'Anglais deu', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(18, 'eng', 'Langue', 3, 'description', 'Anglais eng', '0000-00-00 00:00:00', '0000-00-00 00:00:00');

On crée un modèle « langue.php » sous « model/langue.php » pour puiser les nom des langues dans la base de données et vous constatez que l’on a un $actsAs qui en fait indique que ce modèle est en mode i18n (traduisible) et qu’il a un champ qui s’appelle « description » que l’on retrouve dans la table « i18n » sous la colonne « field »

<?php
class Langue extends AppModel
{
var $name = 'Langue';
var $actsAs = array('Translate' => array('description'));
}
?>

Maintenant nous allons créer un controller « langues_controller.php » sous « controllers/langues_controllers.php » pour gérer 2 actions,  le changement de langue et la liste des langues afin de pouvoir choisir celle de son choix.

<?php
class LanguesController extends AppController {

var $name = 'Langues';
var $components = array('Session');

/*
* Sélectionne une langue sur l'interface du site
* @param 	string (2 char fr/de/en....)
* @return	array
**/
function change($langue_code=null){
// Pour garder la liste déroulante sur la langue courante
$this->Session->Write('langue_code',$langue_code);
// Ajoute le préfixe et change la langue en revenant à la racine du site
$this->redirect('/'.$langue_code.'/');
}

/*
* Liste des langues et crée un cache par langue
* @param 	-
* @return	array
**/
function liste(){
$liste_langues = Cache::read('liste_langues_'.Configure::read('Config.langue_code'));
// Si les langues ne sont pas en cache on fait la mise en cache
if(empty($liste_langues)){
$this->Langue->recursive = 0;
$liste_langues = $this->Langue->find('all');
Cache::write('liste_langues_'.Configure::read('Config.langue_code'),$liste_langues);
}
return $liste_langues;
}

}
?>

Et enfin la vue qui sera un élément « langues.ctp » dans « /views/elements/langues.ctp ».
Super important, pensez à créer un répertoire virtuel http://www.formation-cakephp.com/3/demarrer-un-projet-cakephp, sinon vous aurez le préfix de langue qui va se balader un peu partout au mauvais endroit. Dans mon cas je n’ai pas crée un vhost pour ce projet, mais si vous le créez vous pourrez utiliser vos liens normalement avec le helper i18n.

<?php
$langues = $this->requestAction('langues/liste');
?>

<!-- méthode 1 liste les langues dans un input avec mémorisation de la sélection sur la langue concernée -->
<select id="select_langue" onChange='javascript:window.location.href=document.getElementById("select_langue").options[document.getElementById("select_langue").selectedIndex].value;'>
<?php
$langue_code = $this->Session->Read('langue_code');
foreach($langues as $langue){
if($langue_code==$langue['Langue']['langue_code']){$selected='selected';}else{$selected='';}
echo '<option value="/tuto-langues/langues/change/'.$langue['Langue']['langue_code'].'"'.$selected.'>'.$langue['Langue']['description'].'</option>';
}
?>
</select>

<!-- méthode 1 liste les langues en liens -->
<?php
foreach($langues as $key=>$langue){
echo '<a href="/tuto-langues/langues/change/'.$langue['Langue']['langue_code'].'">'.$langue['Langue']['description'].'</a>';
if($key<>count($langues)-1){echo ' | ';};
}
?>

Et pour clore le tout on appelle l’élément depuis notre « layout.ctp » dans « views/layouts/layout.ctp » en faisant :

echo $this->element('langues');

A présent dans notre layout on rajoute un texte simple et on va tenter de le traduire.

<?php
echo $this->element('langues');
echo '<br/>';
echo __('Salut',true);
?>

5) Extraction avec la console

En gros le concept est le suivant. Une fois l’application terminée, on exporte le fichier de traduction puis on le traduit en différentes langues avec un éditeur. Ensuite on met chaque langue dans un répertoire et cake le lira automatiquement.

D’abord il faut extraire les langues avec la console de cake, sous Windows pour faire marcher la console avec par exemple Wamp vous pouvez faire ceci. Dans les variables d’environnement Windows modifier la variable « Path » et ajoutez les lignes suivantes (à adapter selon vos noms) et ne supprimez pas les variables déjà présentes, ajoutez donc les vôtre à la suite avec toujours les « ; » à la fin.
Dans notre cas nous ajoutons un chemin vers PHP et un chemin vers la console de cakePHP.

C:\wamp\bin\php\php5.2.9-2;C:\wamp\www\cakephp\tuto-langue\cake\console;


N’oubliez pas de rebooter le système une fois que vous avez mis les informations à jour, sinon ça ne marchera pas.
Je conseille ensuite de faire un raccourci « .bat » vers votre application comme ça vous n’avez pas besoin de vous déplacer dans les répertoires.

Ensuite lancez la console avec le raccourci, puis tapez la commande suivante :
cake i18n
– ensuite « E » puis enter, afin d’effectuer une extraction des textes.
– ensuite l’on va vous demander le full path qui devrait être celui de votre projet validez par 2 fois par enter
– définissez le full path des langues, soit dans votre « /app/locales »
– on demande si vous voulez merger toutes les traductions dans un seul fichier, « Y »
L’extraction se lance

6) Poedit

Maintenant on va mettre en production l’anglais sur notre site. Commencez par installer Poedit qui permet d’éditer les fichiers exportés par CakePHP.
Ensuite sous Poedit au menu « fichier->nouveau catalogue depuis un fichier pot » sélectionnez votre fichier « default.po » sous « app/locale » et sauvez votre nouveau fichier « default.po » sous le répertoire de la langue désirée dans notre cas : « app/locale/eng/LC_MESSAGES ».

Modifiez ensuite le texte « Salut » en « Hello world » via Poedit.

Si vous avez des erreurs lors de l’import ou moment de sauver, vous pouvez modifier cette ligne dans le fichier pot.

<pre>#"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
"Plural-Forms: nplurals=2; plural=(n==1? 0 : 1);\n"

Si vous avez des doublons il faudra aussi les supprimer manuellement dans le fichier. Dans mon cas j’avais le problème de doublon sur les clés suivantes :

day
Path: %s

Retournez ensuite sur votre site et sélectionnez l’anglais et à présent votre message s’affiche en anglais. Il faudra enregistrer un fichier default.po pour chacune des nouvelles langues.

Important

Afin de garder un préfixe permanent durant votre application cela exige d’avoir l’oeil sur quelques points notamment au niveau des formulaires.
Je conseille donc de faire attention et de préfixer le formulaire avec le préfixe de la langue au niveau de l’url de l’action. Sinon on pourrait par exemple avoir un utilisateur parlant « Anglais » qui soumet un formulaire mal rempli et comme il manque le préfixe les messages s’afficheraient dans la langue par défaut, dans notre cas le français.

echo $form->create('MonModel',array('url' => '/'.Configure::read('Config.langCode').'/controllers/mon_action'));
NOT NULL AUTO_INCREMENT,

6 commentaires sur “Application multilingue avec CakePHP 1.3”

  1. Merci pour ce très bon tuto!

    Bien que ça ne devrait pas poser de problèmes, je ne mettrai pas « DEFAULT CHARSET=latin1 » aux tables « langues » et « i18n ».


    ALTER TABLE `langues` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci AUTO_INCREMENT=5;
    ALTER TABLE `langues` CHANGE `langue_code` `langue_code` VARCHAR( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    CHANGE `langue_iso` `langue_iso` VARCHAR( 3 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

  2. bonjour ,

    Premièrement je vous remercie de votre tutoriel et il est très utile pour mettre un site multilungue avec cakephp.

    j’ai fait toute la procédure pour mettre la traduction dans mon site mais ça marche pas au niveau du code de la page views/elements/langues.ctp lors de l’appel de l’action liste().Quand j’active la ligne de code : $langues = $this->requestAction(‘langues/liste’); dans langues.ctp le site ne s’affiche pas et mon serveur apache se désactive tout seul sans aucun message d’erreur dans mon site et je ne sais pas comment régler ce problème .
    Et par contre j’ai téléchargé le script de votre exemple de traduction est il marche très bien et aucun problème.

    info : j’utilise la version 1.2.5 de cakephp

    Merci d’avance
    Boulboul

  3. Bonjour,

    Moi j’ai un petit problème, je ne sais pas si je m’y prends mal.
    J’ai suivi le tuto jusqu’à un niveau ou tout mon travail bug, j’explique.

    Juste après l’étape où je cré le fichier i18n.php, j’ai deux types d’erreur
    – Notice (8): Undefined variable: form [APPviewselementsrecherche.ctp, line 2]Code | Contextcreate(‘Recherche’, array(‘action’ => ‘recherche’));
    $___viewFn = « C:wampwwwannuaire_simpleappviewselementsrecherche.ctp »
    $___dataForView = array(
    « liste_themes » => array(
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array()
    ),
    « liste_secteurs_activites » => array(
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array(),
    array()
    ),
    « page » => « home »,
    « subpage » => null,
    « session » => SessionHelper
    SessionHelper::$helpers = NULL
    SessionHelper::$__active = true
    SessionHelper::$valid = false
    SessionHelper::$error = false
    SessionHelper::$_userAgent = « 0f492ef883081cc194a68010839cb9ee »
    SessionHelper::$path = « / »
    SessionHelper::$lastError = NULL
    SessionHelper::$security = NULL
    SessionHelper::$time = 1286557181
    SessionHelper::$sessionTime = false
    SessionHelper::$watchKeys = array
    SessionHelper::$id = NULL
    SessionHelper::$_log = NULL
    SessionHelper::$base = « /annuaire_simple »
    SessionHelper::$webroot = « /annuaire_simple/ »
    SessionHelper::$here = « /annuaire_simple/ »
    SessionHelper::$params = array
    SessionHelper::$action = « display »
    SessionHelper::$data = NULL
    SessionHelper::$themeWeb = NULL
    SessionHelper::$plugin = NULL,
    « i18n » => I18nHelper
    I18nHelper::$tags = array
    I18nHelper::$base = « /annuaire_simple »
    I18nHelper::$here = « /annuaire_simple/ »
    I18nHelper::$params = array
    I18nHelper::$action = « display »
    I18nHelper::$data = NULL
    I18nHelper::$_crumbs = array
    I18nHelper::$__includedScripts = array
    I18nHelper::$_scriptBlockOptions = array
    I18nHelper::$__docTypes = array
    I18nHelper::$helpers = NULL
    I18nHelper::$webroot = « /annuaire_simple/ »
    I18nHelper::$themeWeb = NULL
    I18nHelper::$plugin = NULL
    I18nHelper::$namedArgs = NULL
    I18nHelper::$argSeparator = NULL
    I18nHelper::$validationErrors = NULL
    I18nHelper::$__tainted = NULL
    I18nHelper::$__cleaned = NULL
    I18nHelper::$_log = NULL,
    « html » => HtmlHelper
    HtmlHelper::$tags = array
    HtmlHelper::$base = « /annuaire_simple »
    HtmlHelper::$here = « /annuaire_simple/ »
    HtmlHelper::$params = array
    HtmlHelper::$action = « display »
    HtmlHelper::$data = NULL
    HtmlHelper::$_crumbs = array
    HtmlHelper::$__includedScripts = array
    HtmlHelper::$_scriptBlockOptions = array
    HtmlHelper::$__docTypes = array
    HtmlHelper::$helpers = NULL
    HtmlHelper::$webroot = « /annuaire_simple/ »
    HtmlHelper::$themeWeb = NULL
    HtmlHelper::$plugin = NULL
    HtmlHelper::$namedArgs = NULL
    HtmlHelper::$argSeparator = NULL
    HtmlHelper::$validationErrors = NULL
    HtmlHelper::$__tainted = NULL
    HtmlHelper::$__cleaned = NULL
    HtmlHelper::$_log = NULL
    )
    $loadHelpers = false
    $cached = false
    $loadedHelpers = array()
    $liste_themes = array(
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    ),
    array(
    « Theme » => array(),
    « Domaine » => array()
    )
    )
    $liste_secteurs_activites = array(
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    ),
    array(
    « SecteurActivite » => array(),
    « DomaineActivite » => array()
    )
    )
    $page = « home »
    $subpage = null
    $session = SessionHelper
    SessionHelper::$helpers = NULL
    SessionHelper::$__active = true
    SessionHelper::$valid = false
    SessionHelper::$error = false
    SessionHelper::$_userAgent = « 0f492ef883081cc194a68010839cb9ee »
    SessionHelper::$path = « / »
    SessionHelper::$lastError = NULL
    SessionHelper::$security = NULL
    SessionHelper::$time = 1286557181
    SessionHelper::$sessionTime = false
    SessionHelper::$watchKeys = array
    SessionHelper::$id = NULL
    SessionHelper::$_log = NULL
    SessionHelper::$base = « /annuaire_simple »
    SessionHelper::$webroot = « /annuaire_simple/ »
    SessionHelper::$here = « /annuaire_simple/ »
    SessionHelper::$params = array
    SessionHelper::$action = « display »
    SessionHelper::$data = NULL
    SessionHelper::$themeWeb = NULL
    SessionHelper::$plugin = NULL
    $i18n = I18nHelper
    I18nHelper::$tags = array
    I18nHelper::$base = « /annuaire_simple »
    I18nHelper::$here = « /annuaire_simple/ »
    I18nHelper::$params = array
    I18nHelper::$action = « display »
    I18nHelper::$data = NULL
    I18nHelper::$_crumbs = array
    I18nHelper::$__includedScripts = array
    I18nHelper::$_scriptBlockOptions = array
    I18nHelper::$__docTypes = array
    I18nHelper::$helpers = NULL
    I18nHelper::$webroot = « /annuaire_simple/ »
    I18nHelper::$themeWeb = NULL
    I18nHelper::$plugin = NULL
    I18nHelper::$namedArgs = NULL
    I18nHelper::$argSeparator = NULL
    I18nHelper::$validationErrors = NULL
    I18nHelper::$__tainted = NULL
    I18nHelper::$__cleaned = NULL
    I18nHelper::$_log = NULL
    $html = HtmlHelper
    HtmlHelper::$tags = array
    HtmlHelper::$base = « /annuaire_simple »
    HtmlHelper::$here = « /annuaire_simple/ »
    HtmlHelper::$params = array
    HtmlHelper::$action = « display »
    HtmlHelper::$data = NULL
    HtmlHelper::$_crumbs = array
    HtmlHelper::$__includedScripts = array
    HtmlHelper::$_scriptBlockOptions = array
    HtmlHelper::$__docTypes = array
    HtmlHelper::$helpers = NULL
    HtmlHelper::$webroot = « /annuaire_simple/ »
    HtmlHelper::$themeWeb = NULL
    HtmlHelper::$plugin = NULL
    HtmlHelper::$namedArgs = NULL
    HtmlHelper::$argSeparator = NULL
    HtmlHelper::$validationErrors = NULL
    HtmlHelper::$__tainted = NULL
    HtmlHelper::$__cleaned = NULL
    HtmlHelper::$_log = NULLinclude – APPviewselementsrecherche.ctp, line 2
    View::_render() – COREcakelibsviewview.php, line 718
    View::element() – COREcakelibsviewview.php, line 383
    include – APPviewselementsheader.ctp, line 9
    View::_render() – COREcakelibsviewview.php, line 718
    View::element() – COREcakelibsviewview.php, line 383
    include – APPviewspageshome.ctp, line 1
    View::_render() – COREcakelibsviewview.php, line 718
    View::render() – COREcakelibsviewview.php, line 417
    Controller::render() – COREcakelibscontrollercontroller.php, line 861
    PagesController::display() – APPpages_controller.php, line 94
    Object::dispatchMethod() – COREcakelibsobject.php, line 125
    Dispatcher::_invoke() – COREcakedispatcher.php, line 240
    Dispatcher::dispatch() – COREcakedispatcher.php, line 206
    [main] – APPwebrootindex.php, line 83

    Fatal error: Call to a member function create() on a non-object in C:wampwwwannuaire_simpleappviewselementsrecherche.ctp on line 2

    – Fatal error: Class ‘HtmlHelper’ not found in C:wampwwwannuaire_simpleappviewshelpersi18n.php on line 3

    Ca fait quelques jours que j’essaies de comprendre ce qui cloche mais en vain.
    Si je peux avoir un petit coup de pouce.

    Merci d’avance

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *