IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

multi-langue et POO [POO]


Sujet :

Langage PHP

  1. #1
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut multi-langue et POO
    Bonjour,

    en procédural, je faisais include_once dirname(__DIR__)."\language.".$lang.".inc.php"; et donc selon la valeur de $lang, le tableau $str avait des valeurs traduites dans la bonne langue (par exemple $str['home'] valait 'Accueil' en fr et 'Home' en english).

    Voici ce que j'ai essayé en POO :
    class_lang.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?php
    namespace _classes;
    class class_lang {
    public $str;
    public $lang;
     
    public function __construct() {}
     
    public function init_lang() {
        switch ($this->lang){
            case 'fr':
                $this->str['home']='Accueil';
            break;
     
            case 'en':
                $this->str['home']='Home';
            break;
        }
    }    
     
     
    }
    ?>

    index.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    use _classes\squelette;
    use _classes\class_lang;
     
    $footer  = new squelette();
    $lang = new class_lang();
    $this->lang='fr';
    $lang->init_lang();
     
    $footer->disp_footer();

    La classe squelette contient notamment $footer (la propriété a le même nom que l'objet)

    et
    Fatal error: Uncaught Error: Using $this when not in object context in C:\wamp64\www\eis32_oo\index.php on line 12
    La ligne 12 de index.php est ici la 6.

    Qu'est-ce qui ne va pas ?

  2. #2
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut
    Désolé, j'avais trouvé mais ne me rappelais pas que j'avais trouvé !

  3. #3
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut
    Pour montrer que j'ai compris certaines choses en POO, voici la solution :

    squelette.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    namespace _classes;
    class squelette {
    private $menu;
    private $entete;
    private $footer;
    private $str;
     
    public function __construct(class_lang $lang) {
        $this->str=$lang->str;
    }
     
    public function disp_footer() {
     
            $this->footer = <<< HTML
    code html
    HTML;
            echo $this->footer;
        }
    }
    ?>

    index.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?php
    //autoloading
    include_once 'Autoloader.php';
     
    Autoloader::register();
     
    use _classes\squelette;
    use _classes\class_lang;
     
    $lang = new class_lang();
    $lang->lang='fr';
    $lang->init_lang();
    $footer  = new squelette($lang);
     
    $footer->disp_footer();

  4. #4
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut Laurent,

    on va reprendre un peu tout ça :

    - Quelle est l'utilité d'avoir un espace de nom _classes ? Tout va être une classe alors bon...
    Un espace de nom te permet de ranger et découper ton code en concepts et/ou fonctionnalités.
    Donc, ce que t'aurais dû avoir c'est quelque chose dans ce genre : namespace I18n; ou namespace Translation; ou namespace Internationalization; avec dedans une classe class Translator. Bref un truc logique.

    - Oblige toi à suivre les normes PSR, c'est essentiel dans la facilité de lecture du code pour n'importe quel quidam.

    - La déclaration de l'autoloader doit être incluse dans le fichier inclus, tu ne dois pas avoir à faire Autoloader::register();,

    - Le nommage des classes, celle-là, elle est mortelle : squelette ! Tu fais de la biologie, tu travailles sur un macchabée ou quoi ? Et Layout, ça ne te parle pas ?
    Plus tu resteras proche des standard et plus ça te sera facile et plus facilement tu pourras transcrire des exemples du web à ta sauce.

    - je te conseille très fortement pour la notation hérédoc de suivre les préconisations : c'est <<<html et pas <<< HTML, l'avantage c'est qu'un IDE comme PHPStorm va adapter le parseur interne au langage manipulé.
    Par exemple si je fais en plein code PHP un bloc <<<css, l'autocompletion sera du CSS, pareil pour les autres cas de figure : <<<js, j'aurais tout le langage javascript disponible, <<<html, etc.

    Au final, je ne sais toujours pas ce qu tu souhaites porter en POO, quelles parties de l'app ?

  5. #5
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut
    Salut rawsrc,

    j'ai essayé de prendre en compte tes 5 remarques.

    Voici où j'en suis :

    index.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    //autoloading
    include_once 'Autoloader.php';
     
    use _classes\Layout\Layout;
    use _classes\Lang\Lang;
     
    $Lang = new Lang();
    $Lang->Lang='fr';
    $Lang->InitLang();
    $Footer  = new Layout($Lang);
     
    $footer->DispFooter();

    autoloader.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?php 
     
    class Autoloader {
    static function register() {
        define('DIR_ROOT', __DIR__.DIRECTORY_SEPARATOR);
     
        $autoloader = function($full_class_name) {//echo "autoloader 7 ".$full_class_name."<br/>";
            // on prépare le terrain : on remplace le séparteur d'espace de nom par le séparateur de répertoires du système
            $name = str_replace('\\', DIRECTORY_SEPARATOR, $full_class_name);
            // on construit le chemin complet du fichier à inclure :a
            // il faut que l'autoloader soit toujours à la racine du site
            $path = DIR_ROOT.$name.'.php';
     
            // on vérifie que le fichier existe et on l'inclut
            // sinon on passe la main à une autre autoloader (return false)
            if (is_file($path)) {
                include $path;
                return true;
            } else {
                return false;
            }
        };
        spl_autoload_register($autoloader);
    }
    }
     
    Autoloader::register();

    Lang.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?php
    namespace _classes\Lang;
    class Lang {
    public $Str;
    public $Lang;
     
    public function __construct() {}
     
    public function InitLang() {
        switch ($this->Lang){
            case 'fr':
                $this->Str['home']='Accueil';
            break;
     
            case 'en':
                $this->Str['home']='home';
            break;
        }
    }    
     
     
    }
    ?>

    Layout.php :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php
    namespace _classes\Layout;
    class Layout {
    private $Menu;
    private $EnTete;
    private $Footer;
    private $Str;
     
    public function __construct(Lang $Lang) {
        $this->Str=$Lang->Str;
    }
     
    public function DispFooter() {
              $this->Footer = <<<html
    code html
    html;
            echo $this->Footer;
        }
    }
    ?>

    Le message d'erreur :
    Fatal error: Uncaught TypeError: Argument 1 passed to _classes\Layout\Layout::__construct() must be an instance of _classes\Layout\Lang, instance of _classes\Lang\Lang given, called in C:\wamp64\www\eis32_oo\index.php on line 11 and defined in C:\wamp64\www\eis32_oo\_classes\Layout\Layout.php on line 9
    que je ne comprends pas

    Pour décrire l'appli que je souhaite porter en POO, vu qu'elle n'est pas en ligne, elle n'est pas montrable. Disons que je suis parti d'une appli toute en procédural, fortement dégraissée, mais j'ai quand même laissé quelques fonctionnalités. Et j'essaye de tout porter en POO.

  6. #6
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    voici vers quoi tu dois tendre (nommage, présentation)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <?php 
     
    class Autoloader
    {
        public static function register()
        {
            define('DIR_ROOT', __DIR__.DIRECTORY_SEPARATOR);
     
            $autoloader = function($full_class_name) { //echo "autoloader 7 ".$full_class_name."<br/>";
                // on prépare le terrain : on remplace le séparteur d'espace de nom par le séparateur de répertoires du système
                $name = str_replace('\\', DIRECTORY_SEPARATOR, $full_class_name);
                // on construit le chemin complet du fichier à inclure :a
                // il faut que l'autoloader soit toujours à la racine du site
                $path = DIR_ROOT.$name.'.php';
     
                // on vérifie que le fichier existe et on l'inclut
                // sinon on passe la main à une autre autoloader (return false)
                if (is_file($path)) {
                    include $path;
                    return true;
                } else {
                    return false;
                }
            };
            spl_autoload_register($autoloader);
        }
    }
     
    Autoloader::register();
    Si t'utilises l'autoloader, c'est que tu dois avoir défini un unique point d'entrée du site comme je l'ai expliqué sur mon tuto MVC.
    Tu as vraiment besoin de traduire ton site en anglais ?
    Si oui, alors la langue doit être définie une fois pour toute au moment de la connexion par exemple ou à partir d'une liste déroulante, dans ce cas, tu dois suivre cette valeur en session afin de savoir quelle langue utiliser pour l'affichage.
    Par défaut, on dit que c'est en français.
    Les fichiers de traduction doivent être séparés et utilisés que quand on en a besoin.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    <?php
     
    namespace I18n\Translation;
     
    class Translator
    {
        /**
         * @var string
         */
        private static $default_lang = '';
        /**
         * @var string
         */
        private static $current_lang = '';
        /**
         * Fichiers de traduction
         * Chaque fichier doit renvoyer un tableau [mot clé => traduction]
         * @var array [lang => chemin complet vers le fichier]
         */
        private static $path = [];
        /**
         * Liste des fichiers de traduction chargés
         * @var array [lang => [keyword => translation]]
         */
        private static $parsed = [];
     
        /**
         * @param string $lang
         * @param string $full_path     php file that MUST return an array
         * @param bool   $is_default
         */
        public static function addPath(string $lang, string $full_path, bool $is_default = false): void
        {
            self::$path[$lang] = $full_path;
            if ($is_default) {
                self::$default_lang = $lang;
            }
        }
     
        /**
         * @param string $lang
         */
        public static function setCurrentLang(string $lang): void
        {
            self::$current_lang = $lang;
        }
     
        /**
         * @param string $lang
         */
        public static function setDefaultLang(string $lang): void
        {
            self::$default_lang = $lang;
        }
     
        /**
         * Traduction
         * Renvoie un tableau de valeurs traduites échappées, compatibles HTML
         * Si traduction mansuante : renvoie les mots clés tels quels
         *
         * @param array  [keywords]
         * @return array [keyword => escaped translation]
         */
        public static function tr(array $keywords): array
        {
            $hsc  = function(string $p): string { return htmlspecialchars($p, ENT_QUOTES, 'utf-8'); };
            $data = []; // résultats
     
            $is_available = function(string $lang): bool {
                if (($lang === '') || ( ! isset(self::$path[$lang])) || ( ! is_file(self::$path[$lang]))) {
                    return false;
                }
                // chargement du fichier de traduction si nécessaire
                if ( ! isset(self::$parsed[$lang])) {
                    self::$parsed[$lang] = include self::$path[$lang];
                }
                return true;
            };
     
            foreach ($keywords as $keyword) {
                // si tout est ok alors on stock immédiatement la traduction échappée
                if (isset(self::$parsed[self::$current_lang][$keyword])) {
                    $data[$keyword] = $hsc(self::$parsed[self::$current_lang][$keyword]);
                } else {
                    $current = self::$current_lang;
                    $default = self::$default_lang;
     
                    // si la langue courante est disponible et que le mot clé est défini
                    if ($is_available($current) && isset(self::$parsed[$current][$keyword])) {
                        $translation = self::$parsed[$current][$keyword];
                        $data[$keyword] = $hsc();
                    } elseif ($is_available($default) && isset(self::$parsed[$default][$keyword])) {
                        // sinon on se rabat sur la langue par défaut
                        $translation = self::$parsed[$default][$keyword];
                    } else {
                        // dernière possibilité : rien n'est disponible, on renvoie le mot clé
                        $translation = $keyword;
                    }
                    $data[$keyword] = $hsc($translation);
                }
            }
            return $data;
        }
    }
    pour traduire, il faut juste créer un fichier par langue qui a cette structure super simple : un fichier par exemple fr_lang.php pour les traductions françaises :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
     
    return [
        'home' => 'Accueil',
        'add' => 'Ajouter',
        'save' => 'Enregistrer',
        'not.allowed' => 'Non autorisé',
     
    ];
    Un autre en_lang.php
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php
     
    return [
        'home' => 'Home',
        'add' => 'Add',
        'save' => 'Save',
        'not.allowed' => 'Not allowed',
    ];
    Une fois que tu as créé tes fichiers, il faut juste indiquer à la classe en charge de la traduction à quelle langue il font référence et le chemin système pour les atteindre, dans le chargement de ton app, tu dois juste faire après la déclaration de l'autoloader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    use I18n\Translation\Translator;
     
    Translator::addPath('fr', DIR_PATH.'langues'.DIRECTORY_SEPARATOR.'fr_lang.php', true);   // je suppose que les traductions sont dans un dossier "langues" à la racine du site
    Translator::addPath('en', DIR_PATH.'langues'.DIRECTORY_SEPARATOR.'en_lang.php', false);
     
    // ici tu gères la langue souhaitée par l'utilisateur
    Translator::setCurrentLang('en');
    enfin, dans tes rendus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
     
    namespace Home;
     
    use View\Layout\Page;
    use I18n\Translation\Translator;  // ICI TU AVAIS OUBLIE LE USE DANS TON FICHIER D'OÙ TON ERREUR
     
    class HomePage 
    {
        public function render()
        {
            $page = new Page();
            $trs    = Translator::tr(['home', 'add', 'save']);  // traductions
            // injection des traductions
            $body = <<<html
    <p class="title">{$trs['home']}</p>
    reste du code html
    html;
     
            $page->setBody($body);
            $page->render();
            echo $page->code();
        }
    }
    Il faut que tu visualises schématiquement comment tout s’emboîte, papier et crayon sont de rigueur.

  7. #7
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut
    Il faut que tu visualises schématiquement comment tout s’emboîte, papier et crayon sont de rigueur.
    Là déjà, c'est difficile avec mon handicap car j'écris à la main le moins possible. Non seulement, c'est très lent mais en plus c'est illisible (sauf par moi !).

    Si t'utilises l'autoloader, c'est que tu dois avoir défini un unique point d'entrée du site
    j'utilise wamp et je sais que tu n'aimes pas. Cela dit, pour écrire un script apache, il faut mettre un fichier .htaccess à la racine du site. Petit souci pour créer un tel fichier sous Windows 10, mais avec une petite recherche, j'ai trouvé.
    Dedans, j'ai notamment mis la ligne RewriteRule ^.* http://eis.fr [R=301,L] mais erreur 502 (DNS error) Comment faire ?

    Tu as vraiment besoin de traduire ton site en anglais ?
    J'ai gardé cette option pour ne pas trop simplifier, mais pas obligé ; et je crois que vu que c'est pas simple, je vais le virer...

  8. #8
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 495
    Billets dans le blog
    1
    Par défaut
    Comme j'ai finalement décidé de virer le multi-langues, mais que j'ai un autre problème, j'arrête cette discussion et j'en crée une nouvelle.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Bien créer une application multi-langues ? Unicode ou non ?
    Par Maxime Abbey dans le forum Composants VCL
    Réponses: 28
    Dernier message: 10/09/2007, 18h20
  2. Application multi-langue
    Par JerBi dans le forum EDI
    Réponses: 2
    Dernier message: 15/09/2005, 03h22
  3. [Application multi-langues] Compilateur ou fichier lng ?
    Par Teb dans le forum Composants VCL
    Réponses: 5
    Dernier message: 16/08/2005, 17h48
  4. [CR][.NET] Rapport multi-langue
    Par Harakor dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 16/02/2005, 18h06
  5. [C#] Multi langue - fichier resource.resx
    Par dacamp dans le forum ASP.NET
    Réponses: 5
    Dernier message: 03/06/2004, 17h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo