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

Requêtes MySQL Discussion :

Gestion multilangue ?


Sujet :

Requêtes MySQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 17
    Points
    17
    Par défaut Gestion multilangue ?
    Bonjour,

    Je gère des données en multilingue.
    Pour exemple, stocké en DB :
    IDLigne | IDProduit | IDLangue | Description ...
    1 | 1 | FR | test produit 1 - FR
    2 | 1 | DE | test produit 1 - DE
    3 | 2 | FR | test produit 2 - FR
    4| 2 | DE | test produit 2 - DE
    5| 2 | EN | test produit 2 - EN

    Lors de la sélection d'un produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM produit WHERE IDProduit = 1 AND IDLangue = EN
    Seulement comme tout n'est pas traduit comme pour l'exemple le EN du produit 1 n'est pas encore traduit, je voudrais donc dans ce cas prendre la langue par défaut à la place, je cherche à faire quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM produit WHERE IDProduit = 1 AND IDLangue = EN si pas dispo prendre FR par defaut
    Une idée ?
    Merci de votre aide.

  2. #2
    Membre régulier
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Mars 2016
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Mars 2016
    Messages : 58
    Points : 105
    Points
    105
    Par défaut
    Bonjour,

    Voici une maniere de repondre. Je selectionne toutes les lignes de langue FR avec une jointure gauche sur les libelles en EN.

    Ci joint le code en MS/SQL a adapter pour MySQL

    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
    WITH TMP 
         as (SELECT 1                     as IDLigne, 
                    1                     as IDProduit, 
                    'FR'                  as IDLangue, 
                    'test produit 1 - FR' as [Description] 
             UNION ALL 
             SELECT 2, 
                    1, 
                    'DE', 
                    'test produit 1 - DE' 
             UNION ALL 
             SELECT 3, 
                    2, 
                    'FR', 
                    'test produit 2 - FR ' 
             UNION ALL 
             SELECT 4, 
                    2, 
                    'DE', 
                    'test produit 2 - DE ' 
             UNION ALL 
             SELECT 5, 
                    2, 
                    'EN', 
                    'test produit 2 - EN') 
    SELECT TMP.IDProduit, 
           COALESCE(TMP2.[Description], TMP.[Description]) 
    from   TMP 
           LEFT JOIN TMP TMP2 
                  on TMP2.IDProduit = TMP.IDProduit 
                     AND TMP2.IDLangue = 'EN' 
    WHERE  TMP.IDLangue = 'FR'   

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 17
    Points
    17
    Par défaut Pas plus simple ?
    Y a pas une méthode qui dirait : si pas de résultat alors cherche ca ?

  4. #4
    Membre régulier
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Mars 2016
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Mars 2016
    Messages : 58
    Points : 105
    Points
    105
    Par défaut
    C'est exactement ce que fait le COALESCE :

    Si TMP2.[Description] est Null (libelle Anglais) alors on affiche TMP.[Description] (libelle francais)

  5. #5
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut à tous.

    @ sqllm : c'est bien trop compliqué ce que tu proposes de faire. Il est inutile de faire une jointure pour récupérer la ligne par défaut.

    @ cvneo : cette question a déjà été posé sur ce forum.
    Ce que tu proposes de faire, c'est de prendre en premier la langue 'EN' si elle existe sinon prendre 'FR'.
    Et je suppose que la langue par défaut n'est jamais la même selon la langue principale.

    J'aurai préféré un code numérique, genre en position zéro pour la valeur par défaut et ce qui est >0 la valeur renseignée si elle existe.
    Mais ici, tu utilises un code alphabétique, sans avoir réellement une valeur par défaut.

    Je propose ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * produit where IDProduit= 1 and IDLangue in ('fr', 'en') order by field(IDLangue,'en','fr') limit 1;
    Si la langue 'ES' pour espagnol existe, on récupère la ligne, sinon on récupère 'FR' pour français.
    L'ordre de tri est important ainsi que "limit 1".

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  6. #6
    Membre régulier
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Mars 2016
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Mars 2016
    Messages : 58
    Points : 105
    Points
    105
    Par défaut

    @ sqllm : c'est bien trop compliqué ce que tu proposes de faire. Il est inutile de faire une jointure pour récupérer la ligne par défaut.
    bonjour

    je vois vraiment pas ce qu'une jointure gauche peut avoir de compliquee ? Vu de ma fenetre ta solution me semble d'ailleurs plus complexe. Comme tu le precises le fait de ne pas avoir un code numerique pour la langue et 0 pour la langue par defaut t'obliges a avoir un tri "exotique" (sympa la syntaxe d'ailleurs je vais verifier si on peut faire ca en sql server)

    De plus il est necessaire de rajouter un limit pour ne recuperer que le 1er resultat. Que se passe t'il si on demande les libelles d'une famille de produit ?

    Je veux bien que tu m'expliques en quoi ta solution est plus simple car honnetement je vois pas ?

  7. #7
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut sqllm.

    La question posée est :
    Citation Envoyé par cvneo
    Seulement comme tout n'est pas traduit comme pour l'exemple le EN du produit 1 n'est pas encore traduit, je voudrais donc dans ce cas prendre la langue par défaut à la place,
    Il ne cherche pas à extraire tout un tas de lignes de ça table, mais juste une et une seule ligne. Avec l'approche suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM produit WHERE IDProduit = 1 AND IDLangue = EN
    il récupère la ligne qui si la langue existe et dans le cas contraire rien du tout.
    Afin de toujours récupérer sa ligne, il veut ajouter à sa sélection la langue par défaut, qui elle existera toujours.
    C'est ainsi que j'ai compris le problème.

    En plus, "cvneo" te répond : " Pas plus simple ?" avec le commentaire suivant :
    Citation Envoyé par cvneo
    Y a pas une méthode qui dirait : si pas de résultat alors cherche ca ?
    Je ne fais qu’emboîter mes pas dans les siens, et rien de plus !

    Citation Envoyé par sqllm
    Je veux bien que tu m'expliques en quoi ta solution est plus simple car honnêtement je vois pas ?
    Tu ne connais pas bien MySql car MySql n'admet pas les CTE à l'inverse de Microsoft SQL Server et FireBird.
    Donc ta solution, en l'état, ne peut pas s'exécuter sous MySql.

    Ensuite, tu utilises la jointure parce que tu as en tête la fonction "coalesce()".
    Je ne dis pas que ton approche est fausse car tu obtiendras la même solution que moi.

    L'union et la jointure vont grandement ralentir les performances de la requête et c'est là qu'il y a un problème.

    Comme tu as besoin d'une preuve du fonctionnement de cette requête, voici un exemple :
    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
    105
    106
    107
    108
    109
    110
    111
    112
    113
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    (
      `clef`  int unsigned NOT NULL primary key,
      `val`   char(25)     NOT NULL DEFAULT ' '
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `test` (`clef`, `val`) VALUES
    (0, 'description générale'),(15, 'description client 15')
    --------------
     
    --------------
    select * from test
    --------------
     
    +------+-----------------------+
    | clef | val                   |
    +------+-----------------------+
    |    0 | description générale  |
    |   15 | description client 15 |
    +------+-----------------------+
    --------------
    select * from test where clef in (0, 15) order by clef desc limit 1
    --------------
     
    +------+-----------------------+
    | clef | val                   |
    +------+-----------------------+
    |   15 | description client 15 |
    +------+-----------------------+
    --------------
    select * from test where clef in (0, 11) order by clef desc limit 1
    --------------
     
    +------+----------------------+
    | clef | val                  |
    +------+----------------------+
    |    0 | description générale |
    +------+----------------------+
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    (
      `id`       integer unsigned auto_increment NOT NULL primary key,
      `code`     char(02)                        NOT NULL,
      `libelle`  varchar(255)                    NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `test` (`code`,`libelle`) VALUES
      ('de','allemand'),('en','anglais'),('fr','français'),('it','italien')
    --------------
     
    --------------
    select * from test where code in ('fr', 'en') order by field(code,'en','fr') limit 1
    --------------
     
    +----+------+---------+
    | id | code | libelle |
    +----+------+---------+
    |  2 | en   | anglais |
    +----+------+---------+
    --------------
    select * from test where code in ('fr', 'es') order by field(code,'es','fr') limit 1
    --------------
     
    +----+------+----------+
    | id | code | libelle  |
    +----+------+----------+
    |  3 | fr   | français |
    +----+------+----------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
     
    Appuyez sur une touche pour continuer...
    Il suffit de faire un explain pour se rendre compte que ma solution est plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    --------------
    explain select * from test where code in ('fr', 'en') order by field(code,'en','fr') limit 1
    --------------
     
    +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                       |
    +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
    |  1 | SIMPLE      | test  | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where; Using filesort |
    +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
    Pour améliorer les performances, il faut aussi mettre un "index" sur les colonnes "IDProduit" et "IDLangue".

    Citation Envoyé par sqllm
    De plus il est nécessaire de rajouter un limit pour ne récupérer que le 1er resultat.
    En quoi cela te pose un problème ?

    Citation Envoyé par sqllm
    Que se passe t'il si on demande les libelles d'une famille de produit ?
    Ce n'est pas sa demande. Donc pourquoi veux-tu que je réponde à cette question ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  8. #8
    Membre régulier
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Mars 2016
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Mars 2016
    Messages : 58
    Points : 105
    Points
    105
    Par défaut
    Bonjour @Artemus24,

    Merci pour tes explications

    Effectivement je suis plus a l'aise avec Sqlserver.

    La Cte et les unions ne sont la que pour creer le jeu d'essai et pour m'eviter de creer la table. Dans son cas seule la partie en gras est necessaire puisque la table existe chez lui.

    Je n'avais pas besoin de preuve @Artemus24 je souhaitais juste avoir plus d'explications sur ta demarche

    A+

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 17
    Points
    17
    Par défaut
    Bonjour,

    Merci pour vos solutions

    Pour la langue de base, elle est défini via une variable.

    En quoi cela serait plus simple si il y a un ID numérique ?

  10. #10
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut à tous.

    @ cvneo : est-ce que cette solution te convient ?

    Citation Envoyé par cvneo
    En quoi cela serait plus simple si il y a un ID numérique ?
    Si tu utilises une quelconque valeur comme valeur par défaut, elle ne possède pas nécesairement la plus petite valeur.
    De ce fait, tu dois préciser dans le critère du tri l'ordre que tu veux appliquer, d'où cette solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from produit where IDProduit= 1 and IDLangue in ('fr', 'en') order by field(IDLangue,'en','fr') limit 1;
    Si maintenant, la colonne "IDLangue" est de type "integer" et que la valeur par défaut est en position zéro, la solution est un peu plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from produit where IDProduit= 1 and IDLangue in (7,0) order by IDLangue desc limit 1;
    Le tri est descendant, donc en premier 7 si ce code existe, puis après 0.

    Pourquoi est-ce plus simple ?

    1) si tu indiques zéro comme valeur par défaut, tu n'as plus de questions à te poser.
    Dans tous les cas, cette valeur existe et aura toujours la signification de valeur par défaut.

    Si tu n'utilises pas cette astuce, tu devras mettre dans la requête ce que tu considères comme valeur par défaut.
    Je considère que ce n'est pas propre comme solution.

    3) vu que le code pays est de type alphabétique :
    --> https://fr.wikipedia.org/wiki/Liste_des_codes_ISO_639-1
    si tu veux appliquer un ordre particulier, c'est-à-dire utiliser un code numérique, il faut alors créer une table des langues et mettre dans ta table "Produit", la clef étrangère qui va pointer sur cette table des langues.

    3) la solution alphabétique pour la gestion de la langue par défaut ne peut pas fonctionner pour le tri.
    Car tu seras obliger de mettre la liste entière des langues alphabétiques dans la fonction "field()".
    A moins d'avoir moins d'une dizaine de langue, cette solution n'est pas souple à l'emploi.
    Pourquoi ? Car il faut toujours dissocier les données, des traitements.

    4) le mieux est de gérer la colonne "IDLangue" d'une manière numérique.
    Par exemple, tu mets 1 pour allemand, 2 pour anglais, 3 pour français, 4 pour italien ...
    Voire utiliser un code ISO déjà existant, mais numérique.

    Si la langue par défaut est le français alors tu devrais aussi mettre 0 pour français. Mais il y aura qu'une seule langue par défaut !

    5) Maintenant, je ne sais pas ce que tu cherches à faire et j'ignore ce que représente pour toi "langue par défaut".
    Est-ce une langue par défaut, vu d'une manière générale ?

    Ou est-ce une langue par défaut par secteur géographique ?
    Par exemple : pour l'Europe de l'ouest cela sera plutôt l'anglais, pour l'Europe de l'est, le Russe, pour les pays asiatiques le chinois ...

    6) ne pas oublier, pour améliorer les performances, de mettre un index sur les critères de ta requête.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Points : 17
    Points
    17
    Par défaut
    Bonsoir,

    Merci pour vos explications, cela fonctionne parfaitement.

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

Discussions similaires

  1. [URL rewriting] Gestion multilangue via URL
    Par bannik dans le forum Apache
    Réponses: 2
    Dernier message: 12/11/2012, 17h37
  2. Gestion d'un site multilangue
    Par Aloneghost dans le forum Langage
    Réponses: 4
    Dernier message: 13/10/2010, 11h39
  3. Custom Control pour gestion du Multilangue
    Par kendras dans le forum ASP.NET
    Réponses: 1
    Dernier message: 05/08/2008, 14h26
  4. Réponses: 2
    Dernier message: 06/04/2006, 14h42

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