Lien de navigation par langues entre articles et entre rubriques

pour un site public multilingue configuré « par secteur » (voir http://www.spip.net/fr_article2124.html), avec gestion de lien de traduction entre articles.

Il s’agit de faire apparaitre sur un article ou une rubrique un lien de traduction vers les autres langues du site, dans les conditions suivantes.

Configuration site

La configuration « multilinguisme » d’un tel site est :

-  Activer le menu de langue sur les articles ? Non
-  Activer le menu de langue sur les rubriques ? Oui
-  ... seulement pour les rubriques situées à la racine ? Oui
-  Gérer les liens de traduction ? Oui

De plus, il faut que les structures de chaque branche soient identiques, c’est à dire que l’arborescence du site soit la même dans toutes les langues, ce qui est un cas courant.

Il est facile d’avoir le lien vers les articles traductions d’un article :

<BOUCLE_article(ARTICLES){id_article}>
<BOUCLE_traductions(ARTICLES){traduction}{exclus}{par lang}>
<a href="#URL_ARTICLE" dir="#LANG_DIR">
#LANG
</a>
</BOUCLE_traductions>
</BOUCLE_article>

C’est le code de la langue qui sert de lien (par exemple « en » pour aller vers la traduction en anglais). On peut sophistiquer cela en utilisant le filtre [(#LANG|traduire_nom_langue)] qui donne le nom de la langue, par exemple « English ».

Ce qui est moins immédiat, c’est d’avoir un lien sur les rubriques car le site n’est pas configuré pour, puisque ce sont les liens entre articles qui sont gérés (Spip ne permet pas de gérer directement des liens de traduction entre rubriques)

La précédente contribution de Mortimer Trouver les « traductions » des rubriques donne une méthode pour faire des liens de traduction entre rubriques ayant un article traduit.

Liens entre rubriques

La présente contribution permet d’afficher les liens de traduction entre les rubriques de deux branches (ou plus selon le nombre de langues du site), à condition que les branches par langue soit équivalentes (c’est à dire avec la même structure) et qu’il y ait au moins un article traduit dans les branches considérées, même si l’article traduit se situe plusieurs niveaux en dessous des rubriques.

La logique utilisée est de repérer le niveau hiérarchique (n) de la rubrique sur laquelle on se situe et sur laquelle on veut mettre un lien vers ses traductions [1]. Ensuite on plonge dans la branche de cette rubrique jusqu’à trouver un article traduit [2]. Une fois arrivé sur l’article traduit, on regarde quelle est la hiérarchie de sa traduction (il s’agit donc d’un article situé sur une autre branche-langue), et on déroule cette hiérarchie jusqu’au niveau (n) repéré initialement, qui correspond donc logiquement à la traduction de la rubrique initiale, puisque les branches ont la même structure. On fait la même chose pour toutes les langues.

Voici le contenu de mon squelette « traduction.html »

[(#REM) donne le lien de traduction pour toute une branche, à condition qu'il y ait au moins un article traduit dans la branche]
[(#REM) si c'est un article, affichage des liens vers les traductions de l'article, si elles existent]
<BOUCLE_existe_article(ARTICLES){id_article}>
  <BOUCLE_traductions(ARTICLES){traduction}{exclus}{par lang}>
    <a href="#URL_ARTICLE" dir="#LANG_DIR">#LANG</a>
  </BOUCLE_traductions>
</BOUCLE_existe_article>
  [(#REM) si c'est pas un article, c'est une rubrique : elle n'a pas de traduction directe]
  [(#REM) on regarde s'il y a 1 article dans la branche avec une traduction]
  [(#REM) on fait le lien vers la rubrique du meme niveau hierarchique que la rubrique donnée]
  <BOUCLE_h_rub(HIERARCHIE){id_rubrique}>
  </BOUCLE_h_rub>
   <BOUCLE_article_dependant(ARTICLES){branche}>
    <BOUCLE_traduc(ARTICLES){traduction}{exclus}{par lang}>
      <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
        <a href="#URL_RUBRIQUE" dir="#LANG_DIR">
        <BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
          #LANG
        </BOUCLE_secteur>
        </a>
      </BOUCLE_art_trad>
    </BOUCLE_traduc>
      [(#REM)il n'y a pas de lien]
    <//B_traduc>
   </BOUCLE_article_dependant>
  </B_h_rub>
<//B_existe_article>

Il suffit d’appeler ce squelette à l’endroit où on veut voir apparaitre le lien de traduction dans le squelette principal article ou rubrique (ou autre), avec une simple balise INCLURE

Jusqu’à SPIP 1.8.3

<INCLURE(traduction.php3){id_article}{id_rubrique}>

A partir de SPIP 1.9

<INCLURE(fond=traduction){id_article}{id_rubrique}>

Explication

  • La première partie, entre BOUCLE_existe_article et /BOUCLE_existe_article, affiche le lien de traduction directement dans le cas d’un article traduit (premier cas expliqué au début de la contribution)
  • Ensuite, entre /BOUCLE_existe_article et //B_existe_article, nous sommes dans le cas d’une rubrique, où il faut donc déduire le lien de traduction, selon la logique indiquée précédemment.
  • BOUCLE_h_rub sert uniquement à faire tourner le compteur de boucle, afin de compter le niveau hiérarchique (n) de la rubrique courante ; on utilisera ensuite #_h_rub:TOTAL_BOUCLE qui désigne le compteur de cette boucle vu dans une autre boucle [3] ; on aura donc pour valeur le niveau hiérarchique (n).
  • A partir de la rubrique courante (celle dont on vient de compter le niveau hiérarchique), BOUCLE_article_dependant balaye toute la branche (c’est à dire la rubrique et toutes ses sous-rubriques) à la recherche des articles.
  • Pour chaque article rencontré, BOUCLE_traduc regarde s’il y a des traductions (exclus l’article lui-même, d’où le critère {exclus}) ; s’il y a au moins une traduction, BOUCLE_art_trad déroule la hiérarchie de cette traduction jusqu’au niveau hiérarchique (n) en utilisant le compteur de boucle précédemment calculé : c’est le critère {#_h_rub:TOTAL_BOUCLE,1}. Puisque nous sommes au même niveau hiérarchique et que les branches ont des structures similaires, la rubrique courante est donc la traduction de la rubrique de départ, il suffit de placer son url dans le lien.
  • Comme on peut avoir rencontré plusieurs articles dans la branche, on aura autant de lien de traduction que d’articles rencontrés : c’est trop, un seul suffit ! BOUCLE_secteur a pour but de conserver un seul de ces liens grâce au critère {doublons}. Notez que le critère {id_secteur} ne peut pas remplacer le critère {id_rubrique=#ID_SECTEUR}, car {id_secteur} renvoie toutes les rubriques du secteur.

Notes

[1ça ne peut pas être fait directement, puisqu’il n’y a pas de gestion directe de lien de traduction entre rubriques dans Spip

[2s’il n’y a pas d’article traduit, on ne pourra pas faire le lien

[3voir http://www.spip.net/fr_article898.html pour le compteur de boucle, et voir http://www.spip.net/fr_article2991.html pour la syntaxe #_nom:TEXTE

Discussion

13 discussions

  • Bonjour !

    Testé sur Spip 2.0.9 >> marche bien

    Le seul truc qui serait intéressant d’avoir, ça serais de mettre un cookie de lang en même temps.

    Vous savez le faire ?

    (parceque pour le moment, je suis obligé de rajouter en dur &lang=#LANG sur tout mes liens de rubriques par exemples, sinon je repasse en FR.

    Répondre à ce message

  • hello

    j’ai installé la contrib - ça marche super

    mais comment faire pour que lorsqu’il n’y a pas de traduction pour un article (français) le lien de traduction proposé mène vers le sommaire (anglais) du site ?

    pour le moment je n’arrive qu’à afficher un retour vers le sommaire de la même langue que l’article :

    <BOUCLE_existe_article(ARTICLES){id_article}>
      <BOUCLE_traductions(ARTICLES){traduction}{exclus}{par lang}>
        <a href="#URL_ARTICLE" dir="#LANG_DIR" style="color:#666;">  [(#LANG|traduire_nom_langue)] <img src="#CHEMIN{images/#LANG.gif}" alt="[(#LANG|traduire_nom_langue)]" /></a>
      </BOUCLE_traductions>
      </B_traductions>
      
    <a href="#URL_SITE_SPIP" dir="#LANG_DIR" style="color:#666;">  [(#LANG|traduire_nom_langue)] <img src="#CHEMIN{images/#LANG.gif}" alt="[(#LANG|traduire_nom_langue)]" /></a>
    
    <//B_traductions>
    </BOUCLE_existe_article>

    Répondre à ce message

  • J’utilise cet excellent script, mais les liens ne marchent pas pour les articles se trouvant dans une rubrique de premier niveau dans l’arborescence, cela marche très bien dans les articles se trouvant dans des sous-rubriques ou sous-sous-rubriques.

    Avez-vous le même comportement que moi ?

    Voici mon code tel qu’il est dans mes squelettes.

    Merci

    Chris

    <BOUCLE_existe_article(ARTICLES){id_article}>
     <BOUCLE_traductions(ARTICLES){traduction}{exclus}{par lang}>
        #SET{#LANG,<a href="#URL_ARTICLE" dir="#LANG_DIR"><img src="IMG/drapeau_#LANG.gif" /></a>}
     </BOUCLE_traductions>
    </BOUCLE_existe_article>
     <BOUCLE_h_rub(HIERARCHIE){id_rubrique}>
     </BOUCLE_h_rub>
      <BOUCLE_article_dependant(ARTICLES){branche}>
       <BOUCLE_traduc(ARTICLES){traduction}{exclus}{par lang}>
         <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
          <BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
    
       #SET{#LANG,<a href="#_art_trad:URL_RUBRIQUE" dir="#LANG_DIR"><img src="IMG/drapeau_#LANG.gif" /></a>}
          </BOUCLE_secteur>                                              
            </BOUCLE_art_trad>
    
       </BOUCLE_traduc>
         [(#REM)il n'y a pas de lien]
       <//B_traduc>
      </BOUCLE_article_dependant>
     </B_h_rub>
    <//B_existe_article>
    
    
    [(#GET{fr}|?{#GET{fr},'<a href="index.php?lang=fr"><img src="IMG/drapeau_fr.gif" /></a>'})]
    [(#GET{en}|?{#GET{en},'<a href="index.php?lang=en"><img src="IMG/drapeau_en.gif" /></a>'})]

    Répondre à ce message

  • Bonjour,

    Juste pour dire que cette contrib marche très bien sur spip 2.0.5.
    Donc un grand merci à Bertil et à Zaa pour ses améliorations !!

    Répondre à ce message

  • Merci à ceux qui m’ont répndu j’ai pu résoudre mon problème on m’a apporté la réponse, que je ne pensais pas être réalisable, il fallait ajouter ce code php dans le squelette (je ne pensais pas que du php dans des fichiers .html pouvait être interprété correctement)

    voici le code

    <?php
    $trUrl = urlencode($_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]) ;
    ?>

    Après il suffit d’utiliser la variable

    <? $trUrl ?>

    au niveau de mes liens (ne pas oublier les balises php)

    Merci

    Répondre à ce message

  • Bonjour,

    Je voudrais solliciter votre aide pour la traduction de pages, j’ai un site spip et voudrais faire en sorte à ce que je puisse choisir différentes langue et traduire la page courante, grâce au traducteur google, le problème c’est que je n’arrive pas à récupérer la page courante, j’ai essayer de combiner http://mon_url/#SELF mais ça ne marche pas à cause du / j’ai une suite vide avec // j’ai toute l’URL et le contenu de #SELF mais avec // donc http://mon_url//contenu_self

    Quelqu’un a une idée ?

    Merci

    Répondre à ce message

  • Sympa d’avoir répondu mais, ça n’as pas l’air de marcher complètement chez moi, je suis sous spip 2. Pour décrire ce qu’il se passe, j’ai 4 drapeaux qui s’affichent. Si je suis sur une page française, le drapeau anglais pointe bien sur la traduction anglaise de l’article courant, mais j’ai 3 autres drapeaux qui pointe sur la home avec «  ?lang=xx », je ne crois pas que cela corresponde au fonctionnement de ton code initialement. Je pensais qu’il n’y avait pas ce lien sur la home de la langue courante.

    J’ai aussi un autre bug qui n’a rien a voir avec le code de manu, mais tout les articles se trouvant dans une rubrique de 1er niveau n’affichent pas le lien sur l’article traduit, ça marche seulement pour les articles contenus dans des rubriques de niveau 2 (sous-rubriques) et plus. Est-ce le passage a la V2 qui fait ça ?

    merci

    Répondre à ce message

  • 2

    je vous propose ma version de cette boucle qui permet d’avoir un retour à l’index si la langue n’existe pas pour cette article ou rubrique grace à l’utilisation d’une variable et d’un filtre sur cette variable :

    [(#REM) donne le lien de traduction pour toute une branche, à condition qu’il y ait au moins un article traduit dans la branche]
    [(#REM) si c’est un article, affichage des liens vers les traductions de l’article, si elles existent]


    #SET#LANG,drapeau_#LANG.gif


    [(#REM) si c’est pas un article, c’est une rubrique : elle n’a pas de traduction directe]
    [(#REM) on regarde s’il y a 1 article dans la branche avec une traduction]
    [(#REM) on fait le lien vers la rubrique du meme niveau hierarchique que la rubrique donnée]





    #SET#LANG,drapeau_#LANG.gif


    [(#REM)il n’y a pas de lien]
    /B_traduc>


    /B_existe_article>

    [(#GETde| ?#GETde,’drapeau_de.gif)]
    [(#GETfr| ?#GETfr,’drapeau_fr.gif)]
    [(#GETen| ?#GETen,’drapeau_en.gif)]
    [(#GETru| ?#GETru,’drapeau_ru.gif)]

    • Manu, je trouve ton code trés interressant mais il ne s’affiche pas correctement ici. Si tu peux le remettre en mode « code » ça me serais très utile, merci d’avance.

      Chris

    • Voici le code :

      [(#REM) donne le lien de traduction pour toute une branche, à condition qu'il y ait au moins un article traduit dans la branche]
      [(#REM) si c'est un article, affichage des liens vers les traductions de l'article, si elles existent]
      <BOUCLE_existe_article(ARTICLES){id_article}>
        <BOUCLE_traductions(ARTICLES){traduction}{exclus}{par lang}>
           #SET{#LANG,<a href="#URL_ARTICLE" dir="#LANG_DIR"><img src="IMG/drapeau_#LANG.gif" /></a>}
        </BOUCLE_traductions>
      </BOUCLE_existe_article>
        [(#REM) si c'est pas un article, c'est une rubrique : elle n'a pas de traduction directe]
        [(#REM) on regarde s'il y a 1 article dans la branche avec une traduction]
        [(#REM) on fait le lien vers la rubrique du meme niveau hierarchique que la rubrique donnée]
        <BOUCLE_h_rub(HIERARCHIE){id_rubrique}>
        </BOUCLE_h_rub>
         <BOUCLE_article_dependant(ARTICLES){branche}>
          <BOUCLE_traduc(ARTICLES){traduction}{exclus}{par lang}>
            <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
             <BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
       
          #SET{#LANG,<a href="#_art_trad:URL_RUBRIQUE" dir="#LANG_DIR"><img src="IMG/drapeau_#LANG.gif" /></a>}
             </BOUCLE_secteur>                                              
      	</BOUCLE_art_trad>
      
          </BOUCLE_traduc>
            [(#REM)il n'y a pas de lien]
          <//B_traduc>
         </BOUCLE_article_dependant>
        </B_h_rub>
      <//B_existe_article>
      
      
       [(#GET{de}|?{#GET{de},'<a href="index.php?lang=de"><img src="IMG/drapeau_de.gif" /></a>'})]
       [(#GET{fr}|?{#GET{fr},'<a href="index.php?lang=fr"><img src="IMG/drapeau_fr.gif" /></a>'})]
       [(#GET{en}|?{#GET{en},'<a href="index.php?lang=en"><img src="IMG/drapeau_en.gif" /></a>'})]
       [(#GET{ru}|?{#GET{ru},'<a href="index.php?lang=ru"><img src="IMG/drapeau_ru.gif" /></a>'})]

    Répondre à ce message

  • 1

    Ouh lala ! Belle astuce ! Mille mercis !!
    Ca marche sans problème avec SPIP 1.9.2d

    j’ai juste fait une « micro amélioration ».
    En éditant le code source généré par cette astuce, je me suis aperçu que dans le cas d’une rubrique contenant plusieurs articles, beaucoup de code était généré inutilement, même si il n’était pas apparent sur la page.

    Il s’agit alors de remplacer les lignes suivantes...

    <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
    	<a href="#URL_RUBRIQUE" dir="#LANG_DIR">
            <BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
              #LANG
            </BOUCLE_secteur>
            </a>
    </BOUCLE_art_trad>

    ...par

    <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
    	<BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
          <a href="#_art_trad:URL_RUBRIQUE" dir="#LANG_DIR"><img src="IMG/nav/drap_#LANG.gif" /></a>
    	</BOUCLE_secteur>						
    </BOUCLE_art_trad>

    voila voila.

    encore merci...

    • Zut, une petite erreur c’est glissée dans mon copier/coller

      il faut remplacer par CE code :

      <BOUCLE_art_trad(HIERARCHIE) {id_article} {#_h_rub:TOTAL_BOUCLE,1}>
              <BOUCLE_secteur(RUBRIQUES){id_rubrique=#ID_SECTEUR} {doublons}>
           <a href="#_art_trad:URL_RUBRIQUE" dir="#LANG_DIR">#LANG</a>
              </BOUCLE_secteur>                                               
      </BOUCLE_art_trad>

    Répondre à ce message

  • Salut,

    J’ai ajouté un critère à la <BOUCLE_article_dependant(ARTICLES){branche}> :

    {id_trad!=0} ou {id_trad>0} qui permet de n’effectuer les calculs suivants que sur les articles ayant effectivement une traduction.

    Je ne sais pas vraiment si cela a un impact sur les performances, vu que la boucle suivante ne cherche de toute façon que les traductions...

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom