UNESCO Mali joins 32nd national reforestation campaign launch

Read aloud2 min listen

Environmental initiative

UNESCO Mali joins 32nd national reforestation campaign launch

The 32nd edition, themed “Youth at the Heart of Environmental Citizenship for a Greener and More Resilient Mali,” aligns with national efforts to restore ecosystems, combat desertification and preserve natural resources.
180) { if (buf.trim()) out.push(buf.trim()); buf = w; } else { buf = buf ? (buf + ' ' + w) : w; } }); if (buf.trim()) out.push(buf.trim()); }); return out; } function getVoice() { var voices = synth.getVoices(); var prefix = lang === 'en' ? 'en' : 'fr'; var best = voices.find(function (v) { return v.lang.toLowerCase().startsWith(prefix) && /Google|Natural|Siri|Premium/.test(v.name); }); return best || voices.find(function (v) { return v.lang.toLowerCase().startsWith(prefix); }) || null; } function updateUI(playing, paused) { isPlaying = playing; isPaused = paused; var active = playing && !paused; if (iconPlay && iconPause) { iconPlay.style.display = active ? 'none' : 'block'; iconPause.style.display = active ? 'block' : 'none'; } root.classList.toggle(cfg.c.on, active); if (stopBtn) stopBtn.style.display = playing ? 'inline-flex' : 'none'; if (progressWrap) progressWrap.style.display = playing ? 'block' : 'none'; } function updateProgress() { if (!chunks.length || !progressBar) return; progressBar.style.width = Math.min(100, Math.round(((currentIndex + 1) / chunks.length) * 100)) + '%'; } function startKeepAlive() { clearInterval(keepAliveTimer); keepAliveTimer = setInterval(function () { if (synth.speaking && !synth.paused) { synth.pause(); synth.resume(); } }, 8000); } function stopKeepAlive() { clearInterval(keepAliveTimer); } function speakCurrentChunk() { if (currentIndex >= chunks.length) { stopReading(); if (metaText) metaText.textContent = cfg.done; return; } var utt = new SpeechSynthesisUtterance(chunks[currentIndex]); utt.rate = currentRate; var voice = getVoice(); if (voice) utt.voice = voice; utt.lang = lang === 'en' ? 'en-US' : 'fr-FR'; utt.onend = function () { currentIndex++; updateProgress(); if (isPlaying && !isPaused) speakCurrentChunk(); }; utt.onerror = function (e) { if (e.error !== 'canceled' && e.error !== 'interrupted') { currentIndex++; if (isPlaying && !isPaused) speakCurrentChunk(); } }; updateProgress(); synth.speak(utt); } function startReading() { if (isPaused) { synth.resume(); updateUI(true, false); startKeepAlive(); return; } synth.cancel(); chunks = extractArticleText(); currentIndex = 0; if (!chunks.length) return; updateUI(true, false); startKeepAlive(); speakCurrentChunk(); } function pauseReading() { synth.pause(); updateUI(true, true); stopKeepAlive(); } function stopReading() { synth.cancel(); stopKeepAlive(); currentIndex = 0; updateUI(false, false); if (progressBar) progressBar.style.width = '0%'; } if (playBtn) playBtn.addEventListener('click', function () { if (isPlaying && !isPaused) pauseReading(); else startReading(); }); if (stopBtn) stopBtn.addEventListener('click', stopReading); if (speedBtn) speedBtn.addEventListener('click', function () { speedIdx = (speedIdx + 1) % cfg.speeds.length; currentRate = cfg.speeds[speedIdx]; speedBtn.textContent = cfg.rateFmt.replace('%s', currentRate); if (isPlaying && !isPaused) { synth.cancel(); speakCurrentChunk(); } }); window.addEventListener('beforeunload', function () { synth.cancel(); }); if (typeof synth.onvoiceschanged !== 'undefined') synth.onvoiceschanged = function () { getVoice(); }; })();