begin process at 2010 03 21 12:18:50
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Class et Objet ( POO )

 > CLASS LANG AVEC COOKIE + HTTP_ACCEPT_LANGUAGE

CLASS LANG AVEC COOKIE + HTTP_ACCEPT_LANGUAGE


 Information sur la source

Note :
Aucune note
Catégorie :Class et Objet ( POO ) Classé sous :class, lang, langue, cookie Niveau :Initié Date de création :15/12/2009 Date de mise à jour :15/12/2009 01:58:42 Vu :1 232

Auteur : CrazyShooter

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (4)
Ajouter un commentaire et/ou une note


 Description

Cliquez pour voir la capture en taille normale
Cette classe permet de gérer plusieurs langues pour votre site web.
Celle-ci utilise un fichier class.lang.php, plusieurs fichiers .lng contenant la liste des variables (fr.lng) ainsi que des images .png pour les drapeaux.

La langue de l’utilisateur visitant votre site web est automatiquement récupérée grâce à la variable serveur $_SERVER['HTTP_ACCEPT_LANGUAGE']. Celle-ci est ensuite enregistrée dans un cookie.

Mais l’utilisateur peut très bien choisir la langue souhaitée qui sera passée en $_GET puis à nouveau enregistrée dans un cookie.

Source

  • /**
  • * @author Cr@zy
  • * @version 1.0
  • * @copyright 2009 @ crazyws.fr
  • */
  • class Lang {
  • var $lang;
  • var $load = array();
  • var $listLangs = array();
  • var $subdir = '';
  • private $path = "lang/";
  • private $ext = ".lng";
  • private $default = "fr";
  • public function __construct()
  • {
  • $this->GetLangs();
  • if( !isset($_COOKIE['lang']) ){
  • $_COOKIE['lang'] = substr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2 );
  • }
  • if( isset($_GET['lang']) ){
  • $this->CheckLang($_GET['lang']);
  • } else if( isset($_COOKIE['lang']) ){
  • $this->CheckLang($_COOKIE['lang']);
  • }
  • setcookie("lang", $this->lang, time() + 365 * 24 * 3600);
  • $this->LoadLang();
  • }
  • private function CheckLang($lang)
  • {
  • if( in_array($lang . $this->ext, $this->listLangs) ){
  • $this->lang = $lang;
  • } else {
  • $this->lang = $this->default;
  • }
  • }
  • private function LoadLang()
  • {
  • $file = $this->subdir . $this->path . $this->lang . $this->ext;
  • $handle = fopen($file, "r");
  • if( $handle ){
  • while( !feof($handle) ){
  • $buffer = fgets($handle, 4096);
  • if( (substr($buffer,0,1) == "\n") || (!substr($buffer,0,1)) ){
  • continue;
  • }
  • if( substr($buffer,0,1) == '[' ){
  • $prefix = substr($buffer,1,-3);
  • } else {
  • $buffer = trim($buffer);
  • if( !empty($buffer) ){
  • list($key,$value) = preg_split("/ = /", trim($buffer));
  • $this->load[$prefix][$key] = substr($value,0);
  • }
  • }
  • }
  • }
  • }
  • private function GetLangs()
  • {
  • if( $handle = opendir($this->subdir . $this->path) ){
  • while( false !== ($file = readdir($handle)) ){
  • if( $file != "." && $file != ".." && preg_match("/.lng$/",$file) ){
  • $this->listLangs[] = $file;
  • }
  • }
  • closedir($handle);
  • }
  • }
  • public function SetParams($string, $params=array()){
  • foreach($params as $k => $v){
  • $string = str_replace("{" . $k . "}", $v, $string);
  • }
  • return $string;
  • }
  • }
/**
 * @author Cr@zy
 * @version 1.0
 * @copyright 2009 @ crazyws.fr
 */

class Lang {
	
	var $lang;
	var $load = array();
	var $listLangs = array();
	var $subdir = '';
	private $path = "lang/";
	private $ext = ".lng";
	private $default = "fr";
		
	public function __construct()
	{
		$this->GetLangs();
	
		if( !isset($_COOKIE['lang']) ){
			$_COOKIE['lang'] = substr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2 );
		}
		
		if( isset($_GET['lang']) ){
			$this->CheckLang($_GET['lang']);
		} else if( isset($_COOKIE['lang']) ){
			$this->CheckLang($_COOKIE['lang']);
		}
		
		setcookie("lang", $this->lang, time() + 365 * 24 * 3600);
		
		$this->LoadLang();
	}
	
	private function CheckLang($lang)
	{
		if( in_array($lang . $this->ext, $this->listLangs) ){
			$this->lang = $lang;
		} else {
			$this->lang = $this->default;
		}
	}
	
	private function LoadLang()
	{
		$file = $this->subdir . $this->path . $this->lang . $this->ext;
		$handle = fopen($file, "r");
		if( $handle ){
			while( !feof($handle) ){
				$buffer = fgets($handle, 4096);
				if( (substr($buffer,0,1) == "\n") || (!substr($buffer,0,1)) ){
					continue;
				}
				if( substr($buffer,0,1) == '[' ){
					$prefix = substr($buffer,1,-3);
				} else {
					$buffer = trim($buffer);
					if( !empty($buffer) ){
						list($key,$value) = preg_split("/ = /", trim($buffer));
						$this->load[$prefix][$key] = substr($value,0);
					}
				}
			}
		}
	}
	
	private function GetLangs()
	{
		if( $handle = opendir($this->subdir . $this->path) ){
		    while( false !== ($file = readdir($handle)) ){
		        if( $file != "." && $file != ".." && preg_match("/.lng$/",$file) ){
		        	$this->listLangs[] = $file;
		        }
		    }
		    closedir($handle);
		}
	}
	
	public function SetParams($string, $params=array()){
		foreach($params as $k => $v){
			$string = str_replace("{" . $k . "}", $v, $string);
	    }
	    return $string;
	}
}

 Conclusion

J'espère que cette classe aura sû vous aider.
J'attends vos commentaires ou plutôt vos appréciations bonnes ou mauvaises ^^

Pour plus d'infos et télécharger un exemple : http://www.crazyws.fr/blog/?p=1196


 Historique

15 décembre 2009 01:58:42 :
Caractères erronés dans la description

 Sources du même auteur

UNICODE TO HTML ENTITIES
Source avec Zip Source avec une capture BLACKLAGOON APPS
Source avec Zip REDIMENSIONNER UNE IMAGE PHP (GD VERSION 2 REQUISE)

 Sources de la même categorie

Source avec Zip CLASSE TABLE HTML DYNAMIQUE par LDDL
Source avec Zip GÉNÉRATEUR DE COUCHE DAO POUR SITE WEB À PARTIR D'UNE BASE D... par alexfool
Source avec Zip [PHP5.2] CLASSE PDO par hornetbzz
Source avec Zip POO - LOGGING PACKAGE par Waredan
POO - OBJECT CLASS par Waredan

 Sources en rapport avec celle ci

Source avec Zip CLASSE DATETIME AVEC TRADUCTION par 1030
Source avec Zip POO - LOGGING PACKAGE par Waredan
GESTION D'ERREURS par Luzy
UNE GESTION MULTILINGUE COMPLETE par scriptino
CLASSE PHP PERMETANT DE GERER LE MULTILANGUES par phppro

Commentaires et avis

Commentaire de neigedhiver le 16/12/2009 02:23:23

Salut,

Je viens de survoler ton code et à première vue : ça me plaît énormément. C'est propre, clair et, cerise sur le gâteau, tu utilises correctement readdir() (c'est peut-être un détail pour vous, mais pour moi ça veut dire beaucoup lol plus sérieusement, c'est un peu un de mes chevaux de bataille...)

Quelques remarques :

else if (avec un espace) est un peu moins performant que elseif (sans espace). La raison : PHP interprète le else, puis le if et crée alors une seconde boucle if. Alors que sans espace, PHP sait qu'il s'agit de la même boucle. Oui, c'est vraiment du pinaillage (mais bon, comme mes remarques ne concernent que des détails, je les relève quand même ^^)

La lecture du tableau de langue me paraît... comment dire... trop compliquée pour ce que c'est. Visiblement, tu utilises une syntaxe type fichier INI. Pourquoi ne pas utiliser la fonction native de PHP parse_ini_file() ? C'est quand même plus simple et... BEAUCOUP plus performant, puisque natif à PHP (donc codé en C). Par ailleurs, comme tu utilises une PCRE pour parser chaque ligne, c'est très gourmand en ressources.

Pourquoi ne pas utiliser un itérateur pour parcourir le répertoire, plutôt que readdir() ? Même si tu l'utilises correctement, contrairement à 95% des auteurs des codes qu'on trouve sur phpcs, c'est quand même plus "pratique", plus lisible, plus facile à maintenir et peut-être même plus performant (mais je n'ai aucune conviction pour ce dernier point). Ça donnerait un truc du genre :

private function GetLangs() {
  foreach ($it = new DirectoryIterator($this->subdir . $this->path) as $file) {
    if ($file -> isFile() && '.lng' == substr($file->getFilename(), -4)) {
      $this -> listLangs[] = $file -> getFilename();
    }
  }
}

Ici, l'utilisation de substr() est plus rapide qu'une PCRE, qui n'est par ailleurs pas nécessaire pour un test aussi simple.

La syntaxe :
var $lang;
est une syntaxe PHP4. Même si ça fonctionne encore en PHP5 (pour des raisons de compatibilité) et que c'est rigoureusement à la syntaxe PHP5 (par défaut, une propriété dont la visibilité n'est pas définie, comme c'est le cas avec var, celle-ci est publique), il convient d'écrire :
public $lang;
C'est encore un détail, mais c'est juste pour être rigoureux.

Enfin, je trouve dommage d'utiliser des tableaux pour accéder à une variable de langue. Même si c'est certainement très performant, je préfère la facilité d'écriture pour une perte de performance franchement dérisoire. Personnellement, j'utiliserais une classe supplémentaire, LangCat dont les propriétés (virtuelles, accessibles grâce à la méthode magique __get() ) seraient les variables de langue, dans la catégorie en question. On pourrait alors avoir une syntaxe comme celle-ci :

$lang = new Lang();
echo $lang -> cat -> var;

Autre chose : tu ne gères pas les erreurs. Que se passe-t-il si une langue n'existe pas ? A priori, d'après ce que je comprends du code, aucune clé de langue ne sera disponible.
Que se passe-t-il si la clé de langue n'existe pas ? Comme tu utilises des tableaux auxquels on accède directement depuis le code, on obtient une erreur. Il serait peut-être bon de retourner une valeur par défaut (au moins la clé demandée). Ceci serait possible avec une classe LangCat (qui contrôlerait l'accès aux variables de langue), mais ne l'est pas avec un accès direct au tableau.
Que se passe-t-il si dans le fichier de langue, une phrase contient un signe égal = ? La partie après le signe égal n'est pas prise en compte à cause de preg_split(). D'où l'intérêt de l'utilisation de la fonction parse_ini_file()

Une dernière chose (pour le moment ^^) cette classe est sympa, mais oblige à utiliser une syntaxe de type INI. Ce n'est pas dramatique, mais il pourrait être sympa de permettre l'utilisation de différents modes de stockage : INI, tableau PHP, XML, base de données, etc.
Pour cela, une classe générique qui gère la langue, le format de fichier (une factory), et des classes spécialisées pour chaque type. La factory aurait en charge d'ouvrir le fichier, d'en vérifier le format s'il n'est pas spécifié manuellement, et d'instancier la classe adéquate en fonction du type et de la retourner.
$lang = Lang::open('fichier.xml', LANG::XML);
$lang = Lang::open('autre_fichier.php);
Ce n'est qu'une suggestion.
Et pourquoi pas, proposer des fichiers gettext ?

Autre proposition : permettre la création de fichiers de langue, permettant ainsi de développer aisément une interface d'admin pour traduire dans le back-office ou convertir des fichiers d'un format à l'autre. Là, ça devient plus élaboré. Dans la même veine, proposer une conversion depuis un fichier Excel et/ou CSV (j'ai été confronté à ce problème récemment : le client voulait pouvoir traduire dans un tableur : je récupère le fichier XLS, je l'exporte en CSV et je le passe dans moulinette pour en faire un fichier avec un tableau PHP).

Sinon, je le répète : la classe est bien structurée et le code clair et facile à comprendre. Ca fait plaisir de voir un code comme ça ^^

Commentaire de CrazyShooter le 16/12/2009 10:42:53

Salut,

Tout d'abord merci pour votre "commentaire" très fleuris par rapport à ce que l'on peut voir d'habitude ^^

En ce qui concerne les remarques :

- Pour le 'elseif' je me suis renseigné et en effet il est plus performant!

- Pour la lecture du tableau je suis passé par un parse_ini_file et tout marche bien ^^

- Pour le DirectoryIterator oui pourquoi pas je dirai ;p

- Pour accéder aux variables je préfère un tableau personnellement mais la suggestion était bonne et le problème c'est que pour le jeu que je suis en train de programmer, j'ai des variables d'erreur (error1 error2...) et que pour les appeler j'utilise un iterator...

- Pour la gestion des erreurs, si la langue n'existe pas, la langue par défaut (ici fr) est appelée.
Pour les erreurs si des variables n'existent pas dans le .lng et bin... c'est au dev de faire gaffe :D
Mais sinon oui il aurait été plus judicieux de faire un comparateur avec un fichier patron mais bon pas trop le temps pour ça ^^

- Pour ce qui est l'intégration d'autres modes de stockage oui c'est une bonne idée :)

- Idem pour l'interface admin mais comme je te l'ai dit cette classe n'est qu'un module du jeu que je développe et je voulais faire partager cette classe assez simple et efficace.

Encore merci pour ce commentaire bien fourni et riche en renseignement! Ça change des "ca marche pa" ;p

Je prévois de poster d'autres classes sur mon site, je pense d'ailleurs faire une rubrique indépendante pour mes créations de classes. Avec :

- Une classe de gestion des sessions en base de donnée comprenant une colonne membre qui est settée avec son id si celui-ci se connecte (pour permettre le count des connectés) et l'utilisation d'un garbage collector pour expulser les membres "timeouted" ^^.
- Une class "invite" qui permet de récupérer une liste de contacts hotmail, yahoo, gmail, facebook (facebook connect), etc.. à partir des identifiants de ceux-ci. En gros cette classe enverra un email d'invitation aux contacts sélectionnés pour rejoindre votre site.
- Une class errorhandler pour la gestion des erreurs de type E_ERROR etc... Elle permet de les stocker en base de donnée et de ne pas les afficher à l'utilisateur mais de le prévenir que l'administrateur est au courant (envoi de mail). En parallèe une class mysql sera faite avec gestion du cache mais aussi des erreurs qui seront stockées en bdd.
- Une class de cache pour mettre en cache des objets en cas de ré-instanciation d'une classe mais il en va de même pour les tableaux et variables...
- Et bien d'autres mais ce sera la surprise ^^

Toutes ces classes sont déjà créées sur mon jeu, mais au fil du temps elles évoluent, j'attends donc le moment opportun pour les poster ;)

A bientôt !

Commentaire de CrazyShooter le 22/12/2009 11:41:14

Un petit problème avec la fonction parse_ini_file est qu'il faut mettre des guillemets pour les variables contenant des caractères spéciaux... avec ma fonction non par contre...

Commentaire de lesbgay le 07/02/2010 15:18:28

bonjour CrazyShooter,

je voudrais savoir  si tu pense améliorer  ta class lang après les commentaires de neigedhiver.

Merci en tout cas pour  ta class que je vais mettre deja  sur mon site et si mise a jour constructive je la mettrais  aussitot.

Merci en tout cas de ton partage.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

pb avec le multilangue [ par morpheus262 ] Salut,pour une fois c'est  moi qui ai un probleme avec mon code, erreur assez bizard car j ai deja utilisé ce principe et ca marche tres bie Gros problème de selection de la langue [ par Lapinours ] Chalut les djeuns,bon mon probleme est simple et complexe en meme tps.Dans ma page d'accueil je propose une selection de langue francais - anglais - e faire un site bilingue [ par nsmoez ] BonjourJ'ai un site en englais que j'aimerai lui ajouter la langue française. J'ai commencé par traduire tout le contenu du site en langue française.P Probleme Urgent Cookie/Session en PHP [ par dawda ] Bonjour a tous,Depuis mon changement d'hebergeur j'ai le probleme suivant(De online a Amen).J'ai un systeme de traduction de mes pages web qui via le pb avec mis à jour d bouton d'option + check [ par chardene_amour_de_freddy ] Bonjour, Je suis nouvelle sur le forum et je sui tt aussi novice en php.Je veins auprès de mes confrères et consoeurs developpeur demander d Site 2 langues (cookies [ par kiboumz ]  Bonjour, j'essaie de réaliser un script pour rendre mon site dynamique au point de vue de la langue (français et anglais). Cependant, Ecrire un texte en fonction de langue du navigateur [ par Rimb0 ] Bonjour, Je voudrais afficher un texte différent suivant la langue du navigateur.Voici ce que j'ai écrit :<?php$lang = $_SERVER['HTTP_ACC Site multilingue avec des variables dans les traductions [ par dvdstory ] Bonjour,Je souhaite faire un site multilingue, mais des variables me posent problème, je connais le principe, On detecte la langue du navigateur puis Reflection [ par dorian91 ] Salut a tousVoila j'essaye de m'initier a la reflection en php (dur dur ).J'ai fait un petit script et il me met toujours un warning voici mon code$cl function_exists mais dans une classe [ par cedriclomb ] Bonjour,je cherche une fonction pour tester si une fonction existe mais dans une class exempleif(function_in_class($this->{$act}->getPage()){   


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,889 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales