MySQL site multilingue

gfavier Messages postés 4 Date d'inscription lundi 7 juillet 2003 Statut Membre Dernière intervention 18 novembre 2010 - 18 nov. 2010 à 11:34
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 - 18 nov. 2010 à 17:49
Bonjour à tous, voila mon problème.
Je dois créer un site multilingue avec panel d'administration pour insérer des données en base en différentes langues.
De plus cet outil va s'étendre à d'autres langues par la suite, il est donc pensé de manière dynamique avec un array langues.

Exemple:

$langues = array("fr"=>"Français", "es"=>"Español", "en"=>"English");

Dans le panel, avec une boucle j affiche les input text pour les differentes langues. Si une langue est ajoutée dans le tableau, la boucle gère la création du nouvel input pour cette langue.

Je garde les données d'un input dans un unique champ créer de cette manière:
(bien sûr dans ma classe mysql la fonction mysql_real_escape_string() est utilisée avant insertion en base, l'exemple ci-dessous est simplifié pour expliquer le process)

foreach ($langues AS $key => $value) {
$txt .= "[lang_$key]".$_POST['input['.$key.']]/lang_$key";
}
De cette manière le champ description de l'article aura cet aspect:
[lang_fr]Desc en français/lang_fr[lang_es]Desc en español/lang_es[lang_en]Desc in english/lang_en

Ensuite pour afficher dans le frontend la description de la langue choisie par l'utilisateur, j applique cette regexp sur ce champ:
'/\[lang_([a-z]{2})\](.*?)\[\/lang_\1\]/is'

Jusqu'ici tout va bien... Par contre pour trier la liste des articles sur le champ desc ça devient déja plus compliqué mais faisable en php.
J'ai essayé d'utiliser la fonction REGEXP en mysql mais je ne trouve pas la synthaxe correcte pour recupérer ce champ avec uniquement la description dans la bonne langue.

Question:
Est-ce une bonne méthode?
En effet, le champ text est amené à grossir au fur et à mesure que des langues s'ajouteront...
Par contre c'est assez simple pour récuperer depuis un formulaire de recherche les infos pertinentes avec un LIKE en MySQL.

Auriez-vous une méthode pour gérer les sites multilingues qui seraient plus efficace? Avec insertion en base.
Des conseils?

D'avance, merci à tous!

8 réponses

Le grand Jisay Messages postés 100 Date d'inscription mardi 8 mai 2007 Statut Membre Dernière intervention 18 février 2011 2
18 nov. 2010 à 12:00
Salut,

Je trouve que c'est une bonne méthode. Maintenant pour ton problème de tri sur le champs descr, je ne le ferai pas via Mysql mais via PHP. Je créerai une fonction ou méthode si tu travailles en POO qui trie un tableau contenant les bonnes descriptions de la langue voulue.

Par exemple tu es en français et tu récupère via mysql :
-[lang_fr]Desc1_fr/lang_fr[lang_es]Desc1_es/lang_es[lang_en]Desc1_en/lang_en

-[lang_fr]Desc2_fr/lang_fr[lang_es]Desc2_es/lang_es[lang_en]Desc2_en/lang_en

-[lang_fr]Desc2_fr/lang_fr[lang_es]Desc2_es/lang_es[lang_en]Desc2_en/lang_en

-... ert

Ton tableau fr sera alors :
- Desc1_fr
- Desc2_fr
- Desc3_fr

Et tu trie ton tableau fr.

Il me semble que c'est la meilleure solution (et la plus simple)

Bien à toi,

Le grand Jisay
0
gfavier Messages postés 4 Date d'inscription lundi 7 juillet 2003 Statut Membre Dernière intervention 18 novembre 2010
18 nov. 2010 à 12:25
Salut grand Jisey,

merci pour ta réponse, oui je travaille en POO.
Je me demande si il ne serait pas préférable d'utiliser une table additionnelle avec un clé primaire créée sur 2 champs, (article_id, article_lang)

De cette manière, avec une jointure simple on récupère la ligne adéquat sans charger toutes les langues.
Par exemple:
table principale articles:
AR_ID, AR_PRICE, AR_QUANTITY, ...

table reférence pour chaque langue
ARL_ID, ARL_LANG, ARL_NAME, ARL_DESC
ou ARL_ID=AR_ID et ARL_LANG=(iso2 de chaque langue) clé unique

avec AR_ID=ARR_ID and ARR_LANG=$_SESSION['lang'] on récupère les infos ARL_NAME et ARL_DESC dans la langue voulue.

Par contre si on ajoute une langue et qu'il n'y a pas encore d'entrée en base avec la champ ARR_LANG, la requête retournera rien.

Dans ce cas, dans le backoffice, si le champ d'une langue n'est pas renseigné, au moment de l'insertion ou modification, un check peut soit forcer, soit prendre la langue par défaut pour remplir un champ langue vide.

Et cette solution est préférable pour vous?

Merci!
0
Le grand Jisay Messages postés 100 Date d'inscription mardi 8 mai 2007 Statut Membre Dernière intervention 18 février 2011 2
18 nov. 2010 à 14:21
Salut !

Oui c'est une solution également mais cela implique plus de table. J'ai déjà eu l'occasion de travailler comme cela mais perso je m'y perdait assez rapidement.

La solution de ton premier post, j'ai travaillé avec pendant 2ans. Elle est simple, et on n'a pas une longue liste de table avec les traductions.

Pour mes projets perso, c'est la solution de ton premier post que j'utilise.

Mais bon, chacun ses goûts aussi ;-)

Le grand Jisay
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
18 nov. 2010 à 14:42
Salut,

Perso je n'aime pas vraiment les solutions proposées ici. Je serais plus partisan d'ajouter 2 champs dans ta table :
- Un champ renseignant la langue dans laquelle l'article est écrit : suppression totale de tes balises et création d'une entrée par langue.
- Un (second) identifiant (je suppose ici que chaque entrée dispose d'un déjà identifiant unique), non unique par contre, pour les articles.

Ainsi une sélection d'un article par son identifiant retourne 1 ligne par langue, ce qui te permet :
- De ne pas avoir ni de champ monstrueux ni de table superflue.
- De sélectionner la langue la plus adéquat (merci HTTP_ACCEPT_LANGUAGE) en sachant d'avance la liste des langues disponibles.
- D'associer des éléments extérieurs soit à un article entier (id de l'article) soit spécifiquement à une traduction de l'article (id de l'entrée). Dans le cas de documents contenant du texte c'est très efficace car ne présentant dans une langue que les documents écrits dans cette langue.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
gfavier Messages postés 4 Date d'inscription lundi 7 juillet 2003 Statut Membre Dernière intervention 18 novembre 2010
18 nov. 2010 à 14:59
Salut TychoBrahe,

si je comprend bien ta solution, cela implique que si on a une table avec 15 champs (et seulement 2 champs à traduire), on se retrouve avec:
- id unique
- id de larticle non unique pour chaque langue
- langue
- ... autres champs

Ce qui veut dire que si on a 5 ou 10 langues (j en ai deja 4 par défaut)
Il y aura 5 ou 10 entrées de 15 champs avec pleins de champs identiques (sauf id unique, id article non unique, langue, titre, description qui changent en fonction de la langue), et les 10 autres champs seront toujours identiques.

En terme d'optimisation, je ne suis pas sur que les 2 premières solutions proposées soient moins bien que celle là.
Ou je n ai peut etre pas bien analysé ta réponse?

Je pense que la solution 2, avec une table lié à la principale et contenant comme cle primaire les 2 champs (id_article, lang) est plus simple et moins coûteuse à gérer.
Imaginons qu'il y ait 10 langues, ta table principale a 10 lignes par article, quand les autres solutions n'en ont qu'une.

A vrai dire, je ne suis pas partisan de dupliquer des infos.
Encore une fois je n'ai peut-être pas bien analysé ta réponse.

Merci!
0
gfavier Messages postés 4 Date d'inscription lundi 7 juillet 2003 Statut Membre Dernière intervention 18 novembre 2010
18 nov. 2010 à 15:03
Salut grand Jisey,

je bosse aussi avec cette solution depuis un moment, le point qui me dérange, c'est que plusieurs champs de la table doivent passer en text au lieu de varchar (titre par exemple) systématiquement.
En terme de ressource mysqld je me demande si ce n'est pas mieux de splitter les infos dans 2 tables et réduire les tailles d'un maximum de champ?

Merci pour ton retour!
0
Le grand Jisay Messages postés 100 Date d'inscription mardi 8 mai 2007 Statut Membre Dernière intervention 18 février 2011 2
18 nov. 2010 à 15:46

En terme de ressource mysqld je me demande si ce n'est pas mieux de splitter les infos dans 2 tables et réduire les tailles d'un maximum de champ?


Certainement que oui, c'est mieux mais si on réfléchis bien, combien de champs doivent réellement passer en text ? Tout ce qui est description longue. Pour les autres, titres, ... je ne vois pas quel intérêt il y a de les mettre en text. Il faut alors mettre une restriction sur le nombre de caractères que peut entrer un utilisateur. Un varchar(2500) par exemple reste tout à fait raisonnable pour le process Mysql.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
18 nov. 2010 à 17:49
Il y aura 5 ou 10 entrées de 15 champs avec pleins de champs identiques (sauf id unique, id article non unique, langue, titre, description qui changent en fonction de la langue), et les 10 autres champs seront toujours identiques.

Je en connais pas ta structure de base de données : je me basait sur le fait qu'il existe uniquement un titre et un contenu, et donc aucun champ qui ne se retrouve en doublon (ces deux champs étant différents en fonction de la langue). Après en effet, si certains champs se retrouveraient en doublon il faut les mettre dans une table à part et faire une jointure. Ne t'en fais pas, je ne suis pas non plus favorable à la création de doublons, c'est un procédé abominable.

En terme d'optimisation, je ne suis pas sur que les 2 premières solutions proposées soient moins bien que celle là.

Niveau "optimisation" éviter un traitement "à la main" des données par PHP est très coûteux par rapport à un traitement par le SGBDR. Mais le problème n'est pas là, le problème est plus qu'il faut absolument éviter de stocker des infos qui demandent d'être retraitées derrière (truc avec des balises qu'il faut extraire par exemple).
0
Rejoignez-nous