11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous, c'est mon premier post !

Je suis en train de coder en Javascript, mais je débute un peu.
Je souhaite traduire mon site en utilisant innerHTML, ça fonctionne bien avec une boucle.
Mais là arrivé à un lien, ça ne fonctionne plus! le href semble disparu, ainsi que le texte.

Voici mon code, (l'original contient beaucoup plus d'ids):
<script>
        var translations= { 'en' : 
                                {'title' : 'Title', 'text' : 'English text',  'textlink' : 'English link'},
                            'fr' : 
                                {'title' : 'Titre', 'text' : 'Texte français', 'textlink' : 'Lien en français'}
                          };
        function doTranslate(language) {
            for(id in translations[language]) {
                document.getElementById(id).innerHTML = translations[language][id];
            }
        }
</script>

Et le html qui fonctionne, avec deux images pour liens:
<a href="javascript:doTranslate('fr')"><img src="img/Fr-Flag.png"></a>
<a  href="javascript:doTranslate('en')"><img src="img/UK-Flag.png"></a>
<h2 id="title">Title</h2>

Le code html qui ne fonctionne pas (sauf "English text" qui est bien traduit), mais le lien disparait.
<h3 id="text" class="a b c d">English text<a id="textlink" href="http://google.com" target="_blank" >English link</a>
</h3>

Alors je sais que j'imbrique deux id, qui n'est peut-être pas bon, mais c'est pour vous dire que je suis perdu !

Si quelqu'un a une idée ce serait chouette! Merci Smiley cligne
Modifié par Gaara (07 Apr 2016 - 10:56)
Bonjour,

Tu as très bien identifié le problème tout seul: l'imbrication.

En détail voici ce qui se passe: innerHTML efface tout le contenu présent et le remplace par ce que tu demandes. Au moment où tu arrives sur le H3, la totalité de son contenu et donc y compris le lien qui est à l'intérieur est remplacé; et ensuite, le lien n'existe plus donc il ne peut être atteint ni remplacé à son tour; il a disparu.

Tant que tu auras des id imbriqués, ce sera très très difficile d'arriver au bon résultat avec ta solution. Tu y arriveras peut-être mais ton truc reposera sur un rouleau de scotch et de la ficelle...

A très court terme, tu peux essayer de te baser sur les noeuds texte plutôt que sur les id. Mais c'est extrêmement fragile comme construction.

Il faut absolument que tu te penches sur un système de template pour une solution définitive, fiable et perraine. Ca peut être un système côté serveur, p.ex. twig, smarty, ou sinon il en existe aussi exclusivement en JavaScript, par exemple ceux inclus dans les frameworks comme Meteor, Angular... je doute qu'on puisse les utiliser en standalone cependant. Le plus raisonnable est donc de te diriger vers twig, smarty, ou similaires. Ils ont tous des modules complémentaires spécialisés dans la traduction, voir par exemple celui du duo Symfony+Twig.
Modifié par QuentinC (07 Apr 2016 - 11:20)
Bonjour,
QuentinC a écrit :
Il faut absolument que tu te penches sur un système de template pour une solution définitive, fiable et perraine. Ca peut être un système côté serveur, p.ex. twig, smarty, ou sinon il en existe aussi exclusivement en JavaScript, par exemple ceux inclus dans les frameworks comme Meteor, Angular...

À mon humble avis, un framework type AngularJS (ou même juste MustacheJS & Co...) semble tout indiqué pour ce que tu souhaites faire.
Modifié par SolidSnake (07 Apr 2016 - 11:31)
Ah d'accord.
Ça voudrait dire que je dois tout recommencer!

Ceci dit j'ai une piste, en utilisant if/else :
<script>
        var translations= { 'en' : 
                                {'title' : 'Title', 'text' : 'English text',  'textlink' : 'English link'},
                            'fr' : 
                                {'title' : 'Titre', 'text' : 'Texte français', 'textlink' : 'Lien en français'}
                          };
        function doTranslate(language) {
            for(id in translations[language]) {
                if (id == "text") {
                        document.getElementById("textlink").innerHTML = translations[language]["textlink"];
                        document.getElementById("textlink").setAttribute("href", "http://google.com");
                        }
                else {
                        document.getElementById(id).innerHTML = translations[language][id];
                        }
            }
        }
</script>

Avec ce code le lien est bien traduit, mais c'est le texte avant qui ne l'est pas! je suis pas loin Smiley smile
Modifié par Gaara (07 Apr 2016 - 11:24)
Non, franchement, non, dix fois non, oublie ta technique. Est-ce que tu veux vraiment mettre des centaines de if/else bout à bout ? C'est pas viable ton truc.
Modérateur
Hello,

J'avais déjà fais un truc similaire pour la gestion des langues qui devait fonctionner en local sur iPad (avec stockage du choix en localstorage).

Je me suis basé sur les data- en en créant un par type (content, href, placeholder, ...) -> il n'y en a pas 1000 !

Voici le code :

Un exemple de lien (avec contenu + href) :

<a href="" class="..." data-lang="text1" data-lang-href="link1"></a>


Les boutons pour switcher de langue :

<a class="changeLang" href="FR">FR</a>
<a class="changeLang" href="NL">NL</a>
<a class="changeLang" href="EN">EN</a>


Le tableau des traductions :

var trad = [];

trad['FR'] = [];
trad['NL'] = [];
trad['EN'] = [];


trad['FR']['text1'] = "Mon texte fr";
trad['NL']['text1'] = "Mon texte nl";
trad['EN']['text1'] = "Mon texte en";

trad['FR']['link1'] = "http://www.monsite.fr";
trad['NL']['link1'] = "http://www.monsite.nl";
trad['EN']['link1'] = "http://www.monsite.en";


Le petit script qui va bien pour faire fonctionner le tout :

$(document).ready(function() {

	// Va stocker dans localStorange la langue (par défaut en FR)
	var localStorageLang = localStorage.getItem('lang');

	if (localStorageLang === null) {
		lang = 'FR';
		localStorage.setItem('lang', lang);
		localStorageLang = localStorage.getItem('lang');
	};

	$('body').addClass(localStorageLang);

	setlang(localStorageLang);


	function setlang(Lang){
		$("[data-lang]").each(function(index, el) {
			$(this).html(trad[Lang][$(this).attr("data-lang")]);
		});

		$("[data-lang-title]").each(function(index, el) {
			$(this).attr("title",trad[Lang][$(this).attr("data-lang-title")]);
		});

		$("[data-lang-href]").each(function(index, el) {
			$(this).attr("href",trad[Lang][$(this).attr("data-lang-href")]);
		});
	}

	// Bouton de changement de langue
	$('.changeLang').click(function(){
		lang = $(this).attr('href');
		localStorage.setItem('lang', lang);
		setlang(lang);
		return false;
	});

});



Peut-être à remettre au gout du jour mais l'idée est là.
Gaara a écrit :
Ah d'accord.
Ça voudrait dire que je dois tout recommencer!

Oui et non, par exemple, s'il on prend mustache que je n'ai jamais utilisé jusqu'à aujourd'hui, en quelques lignes de code, ça donne ça :
http://codepen.io/snake/pen/MyrJvZ
<button data-lang="fr">FR</button>
<button data-lang="en">EN</button>
<div id="content">
  <h2 id="title">{{ title }}</h2>
  <h3 id="text" class="a b c d">{{ text }}
    <a id="textlink" href="http://google.com" target="_blank" >{{ textlink }}</a>
  </h3>
</div>

Et le JS :
var content,
    $content = $('#content'),
    tpl = $content.html(),
    translations = {
  'en' : 
  {'title' : 'Title', 'text' : 'English text',  'textlink' : 'English link'},
  'fr' : 
  {'title' : 'Titre', 'text' : 'Texte français', 'textlink' : 'Lien en français'}
};
Mustache.parse(tpl)

var loadContent = function (lang) {
  content = Mustache.render(tpl, translations[lang])
  $content.html(content);
}

$('button[data-lang]').click(function(e){
  e.preventDefault()
  loadContent( $(this).data('lang') )
})

loadContent('fr')

NB : j'utilise dans mon exemple jQuery, mais tu peux faire sans bien sûr ! Smiley ravi