Automatically reads Hebrew text aloud in Duolingo's Hebrew course with a slower TTS rate and an optional button for manual playback, ensuring only one automatic playback per text change.
// ==UserScript==
// @name Duolingo Hebrew Text-to-Speech
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Automatically reads Hebrew text aloud in Duolingo's Hebrew course with a slower TTS rate and an optional button for manual playback, ensuring only one automatic playback per text change.
// @author justsomelearner
// @match https://www.duolingo.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
console.log("Duolingo Hebrew Text-to-Speech script loaded");
// Check if the browser supports the Web Speech API for TTS
if (!('speechSynthesis' in window)) {
alert("Your browser does not support the Web Speech API for text-to-speech");
return;
}
let lastReadText = ''; // Variable to store the last read text
// Function to read the Hebrew text aloud
function readText(text) {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'he-IL'; // Set the language to Hebrew
utterance.rate = 0.8; // Set the rate to be slower than the default
speechSynthesis.speak(utterance);
console.log("Reading text: ", text);
}
// Function to add a TTS button next to Hebrew text
function addTTSButton() {
console.log("Attempting to add TTS button");
// Select the Hebrew text element
const hebrewTextElement = document.querySelector('#root > div.kPqwA._2kkzG > div._3yE3H > div > div.RMEuZ._1GVfY > div > div > div > div > div._34aEz._1IiFg.f7WE2._3rat3 > div.aMPis._35mGI > span > span > span');
console.log("Hebrew text element: ", hebrewTextElement);
if (hebrewTextElement && !document.getElementById('ttsButton')) {
const ttsButton = document.createElement('button');
ttsButton.id = 'ttsButton';
ttsButton.innerText = '🔊';
ttsButton.style = 'background-color: #1cb0f6; color: white; border: none; padding: 10px; margin-left: 10px; cursor: pointer; border-radius: 50%; width: 40px; height: 40px;';
ttsButton.onclick = () => readText(hebrewTextElement.textContent);
hebrewTextElement.parentElement.appendChild(ttsButton);
console.log("TTS button added");
} else {
console.log("Hebrew text element not found or TTS button already exists");
}
}
// Function to find and read the Hebrew text automatically
function readHebrewText() {
console.log("Attempting to read Hebrew text");
// Select the Hebrew text element
const hebrewTextElement = document.querySelector('#root > div.kPqwA._2kkzG > div._3yE3H > div > div.RMEuZ._1GVfY > div > div > div > div > div._34aEz._1IiFg.f7WE2._3rat3 > div.aMPis._35mGI > span > span > span');
console.log("Hebrew text element: ", hebrewTextElement);
if (hebrewTextElement) {
const text = hebrewTextElement.textContent;
if (text !== lastReadText) {
readText(text);
lastReadText = text; // Update the last read text
} else {
console.log("Text has already been read");
}
} else {
console.log("Hebrew text element not found");
}
}
// Observe changes in the Duolingo interface to read the text when it changes
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length || mutation.removedNodes.length) {
console.log("Mutation observed");
readHebrewText();
addTTSButton();
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
// Initial call to read the text if it's already there and add the button
window.addEventListener('load', () => {
console.log("Page loaded");
readHebrewText();
addTTSButton();
});
})();