Verwendung der Web Speech API für mehrsprachige Übersetzungen

Avatar of Steven Estrella
Steven Estrella am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Schon in den frühen Tagen der Science-Fiction haben wir über Maschinen fantasiert, die mit uns sprechen. Heute ist das alltäglich. Trotzdem ist die Technologie, um Websites zum Sprechen zu bringen, noch ziemlich neu.

Wir können unsere Webseiten zum Sprechen bringen, indem wir den SpeechSynthesis-Teil der Web Speech API verwenden. Dies gilt immer noch als experimentelle Technologie, hat aber eine großartige Unterstützung in den neuesten Versionen von Chrome, Safari und Firefox.

Der Spaß für mich besteht darin, diese Technologie mit Fremdsprachen zu nutzen. Dafür bieten Mac OSX und die meisten Windows-Installationen auf allen Browsern eine hervorragende Unterstützung. Chrome lädt eine Reihe von Stimmen remote, sodass, wenn Ihr Betriebssystem keine internationalen Stimmen installiert hat, verwenden Sie einfach Chrome. Wir werden einen dreistufigen Prozess durchlaufen, um eine Seite zu erstellen, die denselben Text in mehreren Sprachen spricht. Einige der grundlegenden Code stammen aus der hier gefundenen Dokumentation, aber das Endprodukt fügt einige unterhaltsame Funktionen hinzu und kann auf meinem Polyglot CodePen hier eingesehen werden.

Screenshot der fertigen Polyglot-App mit einem Menü von Sprachen.

Schritt 1: Einfach anfangen

Lassen Sie uns eine einfache Seite mit einem <textarea> für den Text erstellen, den die Seite sprechen soll, und einen Button hinzufügen, der angeklickt wird, um die Sprache auszulösen.

<div id="wrapper">
  <h1>Simple Text To Speech</h1>
  <p id="warning">Sorry, your browser does not support the Web Speech API.</p>  
  <textarea id="txtFld">I love the sound of my computer-generated voice.</textarea>
  <label for="txtFld">Type text above. Then click the Speak button.</label>
  <div>
    <button type="button" id="speakBtn">Speak</button>
    <br>
    <p>Note: For best results on a Mac, use the latest version of Chrome, Safari, or FireFox. On Windows, use Chrome.</p>
  </div>
</div>

Der Absatz mit der ID warning wird nur angezeigt, wenn JavaScript keine Unterstützung für die Web Speech API erkennt. Beachten Sie auch die ID-Werte für das textarea und den button, da wir diese in unserem JavaScript verwenden werden.

Sie können das HTML beliebig gestalten. Sie können auch von der von mir erstellten Demo abweichen

Siehe den Pen
Text-to-Speech Teil 1
von Steven Estrella (@sgestrella)
auf CodePen.

Das Hinzufügen einer Stilregel für den deaktivierten Zustand des Buttons ist eine gute Idee, um Verwirrung bei den wenigen Leuten zu vermeiden, die noch inkompatible Browser verwenden, wie den jetzt charmanten Internet Explorer. Außerdem verwenden wir eine Stilregel, um die Warnung standardmäßig auszublenden, damit wir kontrollieren können, wann sie tatsächlich benötigt wird.

button:disabled {
  cursor: not-allowed;
  opacity: 0.3;
}

#warning {
  color: red;
  display: none;
  font-size: 1.4rem;
}

Nun zur JavaScript! Zuerst fügen wir zwei Variablen hinzu, die als Referenzen auf den „Speak“-Button, der die Sprache auslöst, und auf das <textarea>-Element dienen. Ein Event-Listener am Ende des Codes weist das Dokument an, zu warten, bis die DOM-Elemente geladen sind, bevor die Funktion init() aufgerufen wird. Ich habe eine praktische Hilfsfunktion verwendet, die ich „qs“ nenne und die am Ende des Codes definiert ist. Es ist eine Kurzform-Alternative zu document.querySelector und wählt den Wert des Selektors aus, den ich ihr übergebe, und gibt eine Objektreferenz zurück. Dann fügen wir dem speakBtn-Objekt einen Event-Listener hinzu, damit der Button die Funktion talk() aufruft.

Die Funktion talk() erstellt eine neue Instanz des Objekts SpeechSynthesisUtterance, das Teil der Web Speech API ist. Sie fügt den Text aus dem <textarea> (mit der ID txtFld) zur text-Eigenschaft hinzu. Dann wird die Äußerung an die speechSynthesis-Methode des window-Objekts übergeben und wir hören den gesprochenen Text. Die spezifische Stimme, die Sie hören, variiert je nach Browser und Betriebssystem. Auf meinem Mac ist beispielsweise meine Standardsprache auf amerikanisches Englisch eingestellt und die Standardstimme für Englisch ist Alex. In Schritt 2 fügen wir Code hinzu, um ein Menü zu erstellen, das dem Benutzer hilft, Stimmen für alle verfügbaren Sprachen auszuwählen.

let speakBtn, txtFld;

function init() {
  speakBtn = qs("#speakBtn");
  txtFld = qs("#txtFld");
  speakBtn.addEventListener("click", talk, false);
  if (!window.speechSynthesis) {
    speakBtn.disabled = true;
    qs("#warning").style.display = "block";
  }
}

function talk() {
  let u = new SpeechSynthesisUtterance();
  u.text = txtFld.value;
  speechSynthesis.speak(u);
}

// Reusable utility functions
function qs(selectorText) {
  // Saves lots of typing for those who eschew jQuery
  return document.querySelector(selectorText);
}

document.addEventListener('DOMContentLoaded', function (e) {
  try {init();} catch (error) {
    console.log("Data didn't load", error);
  }
});

Schritt 2: Ein Menü internationaler Stimmen

Wenn wir etwas anderes als die Standardsprache und Sprechstimme verwenden möchten, müssen wir etwas mehr Code hinzufügen. Das werden wir also als nächstes angehen.

Wir werden ein select-Element hinzufügen, das das Menü der Sprachoptionen enthält

<h1>Multilingual Text To Speech</h1>
<div class="uiunit">
  <label for="speakerMenu">Voice: </label>
  <select id="speakerMenu"></select> speaks <span id="language">English.</span>
  <!-- etc. -->
</div>

Bevor wir den Code zum Füllen der Menüoptionen erstellen, sollten wir uns um den Code kümmern, der uns hilft, Sprachcodes ihren entsprechenden Namen zuzuordnen. Jede Sprache wird durch einen zweibuchstabigen Code identifiziert, z. B. „en“ für Englisch oder „es“ für Español (Spanisch). Wir nehmen eine einfache Liste dieser Codes und ihrer entsprechenden Sprachen und erstellen ein Array von Objekten im Format: {"code": "pt", "name": "Portuguese"}. Dann benötigen wir eine Hilfsfunktion, die uns hilft, ein Array von Objekten nach dem Wert einer bestimmten Eigenschaft zu durchsuchen. Wir werden sie in wenigen Minuten verwenden, um schnell den Sprachnamen zu finden, der dem Sprachcode der ausgewählten Stimme entspricht. Kopieren Sie den folgenden Code, sodass die beiden Funktionen direkt über und direkt unter dem Kommentar // Generic Utility Functions stehen.

function getLanguageTags() {
  let langs = ["ar-Arabic","cs-Czech","da-Danish","de-German","el-Greek","en-English","eo-Esperanto","es-Spanish","et-Estonian","fi-Finnish","fr-French","he-Hebrew","hi-Hindi","hu-Hungarian","id-Indonesian","it-Italian","ja-Japanese","ko-Korean","la-Latin","lt-Lithuanian","lv-Latvian","nb-Norwegian Bokmal","nl-Dutch","nn-Norwegian Nynorsk","no-Norwegian","pl-Polish","pt-Portuguese","ro-Romanian","ru-Russian","sk-Slovak","sl-Slovenian","sq-Albanian","sr-Serbian","sv-Swedish","th-Thai","tr-Turkish","zh-Chinese"];
  let langobjects = [];
  for (let i=0;i<langs.length;i++) {
    let langparts = langs[i].split("-");
    langobjects.push({"code":langparts[0],"name":langparts[1]});
  }
  return langobjects;
}

// Generic Utility Functions
function searchObjects(array, prop, term, casesensitive = false) {
  // Searches an array of objects for a given term in a given property
  // Returns an array of only those objects that test positive
  let regex = new RegExp(term, casesensitive ? "" : "i");
  let newArrayOfObjects = array.filter(obj => regex.test(obj[prop]));
  return newArrayOfObjects;
}

Jetzt können wir die Optionen für das select-Element mit JavaScript aufbauen. Wir müssen Variablen am Anfang unseres JavaScript deklarieren, um Referenzen auf das #speakerMenu-Select-Element, das #language-Span-Element, das Array der synthetisierten Stimmen (allVoices), ein Array von Codes zur Identifizierung der Sprachen (langtags) und einen Ort zur Verfolgung der aktuell ausgewählten Stimme (voiceIndex) zu speichern. Fügen Sie diese direkt nach den beiden Variablendeklarationen ein, die wir in Schritt 1 erstellt haben.

let speakBtn, txtFld, speakerMenu, language, allVoices, langtags;
let voiceIndex = 0;

Die aktualisierte Funktion init() legt einige zusätzliche Referenzen auf #speakerMenu und das #language-Span fest und legt alle Sprachcodes in ein Array von Objekten namens langtags. Der Feature-Detection-Teil des Codes ändert sich hier ebenfalls. Wenn die Web Speech API unterstützt wird, wird die Funktion setUpVoices() aufgerufen. Außerdem müssen wir für Chrome auf Änderungen an den geladenen Stimmen lauschen und das Setup bei Bedarf wiederholen. Chrome fragt die verfügbaren Stimmen jedes Mal ab, wenn Sie zwischen einer seiner Remote-Stimmen (denen, die mit dem Google-Präfix aufgeführt sind, während Sie sich in Chrome befinden) und allen anderen Stimmen, die lokal im Betriebssystem des Benutzers gespeichert sind, wechseln.

function init() {
  speakBtn = qs("#speakBtn");
  txtFld = qs("#txtFld"); 
  speakerMenu = qs("#speakerMenu");
  language = qs("#language");
  langtags = getLanguageTags();
  speakBtn.addEventListener("click", talk, false);
  speakerMenu.addEventListener("change", selectSpeaker, false);
  if (window.speechSynthesis) {
    if (speechSynthesis.onvoiceschanged !== undefined) {
      // Chrome gets the voices asynchronously so this is needed
      speechSynthesis.onvoiceschanged = setUpVoices;
    }
    setUpVoices(); // For all the other browsers
  } else{
    speakBtn.disabled = true;
    speakerMenu.disabled = true;
    qs("#warning").style.display = "block";
  }
}

Die Funktion setUpVoices() ruft ein Array von sogenannten SpeechSynthesisVoice-Objekten ab, indem sie die Methode getVoices() des speechSynthesis-Objekts aufruft. Dies geschieht in unserem Code mit der Funktion getAllVoices(). Leider habe ich festgestellt, dass die Methode speechSynthesis.getVoices() manchmal Duplikate in der Liste zurückgibt, daher habe ich neun Codezeilen darauf verwendet, diese zu eliminieren. Schließlich habe ich am Ende von getAllVoices() jedem SpeechSynthesisVoice-Objekt eine eindeutige Kennung Nummer hinzugefügt. Das wird uns in Schritt 3 helfen, wenn wir die Liste der Stimmen filtern müssen, um nur Stimmen für eine bestimmte Sprache anzuzeigen. Wenn abgeschlossen, enthält das allVoices-Array Objekte, die wie die unten gezeigten aussehen. Jedes Objekt hat die Attribute id, voiceURI, name und lang. Das Attribut localService gibt an, ob der Code für die Stimme auf dem Computer des Benutzers oder remote auf den Servern von Google gespeichert ist. Beachten Sie das Attribut lang. Der Wert besteht aus einem zweibuchstabigen Sprachcode (z. B. „es“ für Spanisch), gefolgt von einem Bindestrich und einem Regionscode (z. B. „MX“ für Mexiko). Dies identifiziert die Sprache und den regionalen Akzent jeder Stimme.

{id:48, voiceURI:"Paulina", name:"Paulina", lang: "es-MX", localService:true},
{id:52, voiceURI:"Samantha", name:"Samantha", lang: "en-US", localService:true},
{id:72, voiceURI:"Google Deutsch", name:"Google Deutsch", lang: "de-DE", localService:false}

Die letzte Zeile von setUpVoices() ruft eine Funktion auf, um die Liste der Optionen zu erstellen, die im #speakerMenu-Select-Element erscheinen werden. Der Wert des id-Attributs für jede Stimme wird in das value-Attribut der Option eingefügt. Die Attribute name und lang sind die sichtbaren Textelemente, die in jeder Option zusammen mit „(premium)“ für die Stimmen angezeigt werden, die auf einigen Betriebssystemen und Browsern als solche gekennzeichnet sind.

function setUpVoices() {
  allVoices = getAllVoices();
  createSpeakerMenu(allVoices);
}

function getAllVoices() {
  let voicesall = speechSynthesis.getVoices();
  let vuris = [];
  let voices = [];

  voicesall.forEach(function(obj,index) {
    let uri = obj.voiceURI;
    if (!vuris.includes(uri)) {
      vuris.push(uri);
      voices.push(obj);
    }
  });

  voices.forEach(function(obj,index) {obj.id = index;});
  return voices;
}

function createSpeakerMenu(voices) {
  let code = ;

  voices.forEach(function(vobj,i) {
    code += `<option value=${vobj.id}>`;
    code += `${vobj.name} (${vobj.lang})`;
    code += vobj.voiceURI.includes(".premium") ? ' (premium)' : ;
    code += `</option>`;
  });

  speakerMenu.innerHTML = code;
  speakerMenu.selectedIndex = voiceIndex;
}

Sie erinnern sich vielleicht, dass wir in der Funktion init() einen Event-Listener eingerichtet haben, der selectSpeaker() aufruft, wenn sich speakerMenu ändert. Die Funktion selectSpeaker() speichert den selectedIndex des #speakerMenu-Select-Elements. Als Nächstes holt sie den Wert des ausgewählten Elements, der eine Ganzzahl ist, die dem Index dieser Stimme im allVoices()-Array entspricht. So haben wir nun die gewünschte SpeechSynthesisVoice abgerufen. Dann extrahieren wir die ersten beiden Buchstaben des lang-Attributs (z. B. „en“, „es“, „ru“, „de“, „fr“) und verwenden diesen Code, um das langtags-Array von Sprachobjekten zu durchsuchen, um den entsprechenden Sprachnamen zu finden. Die Funktion searchObjects() gibt ein Array zurück, das wahrscheinlich nur einen Eintrag haben wird. Unabhängig davon ist der erste Eintrag (langcodeobj[0]) alles, was wir brauchen. Schließlich weisen wir diesen Namen dem innerHTML-Attribut des language-span zu, und er wird wie erwartet auf dem Bildschirm angezeigt.

// Code for when the user selects a speaker
function selectSpeaker() {
  voiceIndex = speakerMenu.selectedIndex;
  let sval = Number(speakerMenu.value);
  let voice = allVoices[sval];
  let langcode = voice.lang.substring(0,2);
  let langcodeobj = searchObjects(langtags, "code", langcode);
  language.innerHTML = langcodeobj[0].name;
}

Das Einzige, was noch fehlt, damit Schritt 2 abgeschlossen ist, ist sicherzustellen, dass die Funktion talk() funktioniert, wenn wir auf den „Speak“-Button klicken. Modifizieren Sie die Funktion talk(), um Attribute zur Äußerung hinzuzufügen, um zu steuern, welche Stimme und Sprache verwendet werden und wie schnell der Text gesprochen wird. In meinen Tests funktioniert ein Ratenbereich von 0,5 bis 2 zuverlässig gut. Ich habe festgestellt, dass eine Rate unter 0,5 keine Auswirkung hat. Ich denke, 0,8 ist eine gute Standardeinstellung für viele Sprachen, aber wie wir in Schritt 3 sehen werden, gibt es eine einfache Möglichkeit, den Benutzer entscheiden zu lassen.

function talk() {
  let sval = Number(speakerMenu.value);
  let u = new SpeechSynthesisUtterance();
  u.voice = allVoices[sval];
  u.lang = u.voice.lang;
  u.text = txtFld.value;
  u.rate = 0.8;
  speechSynthesis.speak(u);
}

Das war's für Schritt 2! Hier ist das Ergebnis dessen, was wir bisher getan haben

Siehe den Pen
Text-to-Speech Teil 2
von Steven Estrella (@sgestrella)
auf CodePen.

Spielen Sie ein bisschen damit herum. Manchmal ist es lustig, eine englische Phrase einzugeben und dann einem französischen oder deutschen Sprecher zuzuweisen, sie zu sagen. Umgekehrt, wenn Sie Ihren schlimmsten Spanischschüler aus dem ersten Jahr hören möchten, geben Sie eine spanische Phrase ein und weisen Sie sie einer englischen Stimme zu.

Schritt 3: Das vollständige Polyglot

Wir sind in der Endphase! Einige der Dinge, die wir in diesem Schritt tun, sind kleine Verschönerungen der UI, aber es gibt auch einige funktionale Dinge, die wir tun müssen, um alles abzurunden. Insbesondere werden wir

  • Ein Menü mit verfügbaren Sprachoptionen erstellen
  • Benutzern erlauben, die Geschwindigkeit der Sprache zu definieren
  • Einen Standardspruch in das Textfeld definieren, der bei der Sprachauswahl übersetzt wird

Hier ist, was wir uns ansehen

Wir fügen ein Dropdown-Menü, eine Einstellung für die Sprechgeschwindigkeit und einen Standardspruch hinzu.

Im HTML fügen wir ein neues <select>-Element für das Sprachmenü und eine numerische input hinzu (die später verwendet wird, um die Sprechgeschwindigkeit einzustellen). Beachten Sie, dass wir das #language-Span gelöscht haben, da es nicht mehr relevant ist, sobald das Sprachmenü funktioniert.

<div class="uiunit">
  <label for="languageMenu">Language: </label>
  <select id="languageMenu">
    <option selected value="all">Show All</option>
  </select>
</div>

<div class="uiunit">
  <label for="speakerMenu">Voice: </label><select id="speakerMenu"></select>
</div>

<div class="uiunit">
  <label for="rateFld">Speed: </label>
  <input type="number" id="rateFld" min="0.5" max="2" step="0.1" value="0.8" />
</div>

In JavaScript müssen wir die Variablendeklarationen ändern. Wir werden alle Dialekte im Array allLanguages und nur die Hauptsprachen im Array primaryLanguages verfolgen. Die Arrays langhash und langcodehash dienen als Hash-Tabellen, damit wir schnell einen Sprachnamen erhalten können, wenn wir nur den zweibuchstabigen Sprachcode kennen und umgekehrt. Wir müssen das Sprachmenü nur einmal einrichten, sodass ein boolesches Flag für initialSetup nützlich sein wird.

let speakBtn, txtFld, speakerMenu, allVoices, langtags;
let voiceIndex = 0;
let allLanguages, primaryLanguages, langhash, langcodehash;
let rateFld, languageMenu, blurbs;
let initialSetup = true;
let defaultBlurb = "I enjoy the traditional music of my native country.";

In der neuen Funktion init() entfernen wir die Zeile language = qs("#language"); und fügen dann den neuen Code hinzu, wie hier gezeigt, um die Stichpunkte zu erstellen, auf das numerische rateFld-input und das languageMenu-select zu verweisen und Hash-Tabellen zum Nachschlagen von Sprachnamen und -tags zu erstellen.

function init() {
  // ...keep existing content but delete language = qs("#language");
  createBlurbs();
  rateFld = qs("#rateFld");
  languageMenu = qs("#languageMenu"); 
  languageMenu.addEventListener("change", selectLanguage, false);
  langhash = getLookupTable(langtags, "name");
  langcodehash = getLookupTable(langtags, "code");

  if (window.speechSynthesis) {
    // ...keep existing content
  } else{
    // ...keep existing content
    languageMenu.disabled = true;
  }
}

Die Funktion setUpVoices() muss einige Anpassungen vornehmen, um das neue Sprachmenü zu unterstützen und die Funktion filterVoices() aufzurufen, die wir jetzt verwenden werden, um das #speakerMenu-Element zu füllen. Außerdem fügen wir die neuen Funktionen hinzu: getAllLanguages() und getPrimaryLanguages(). Die erste sammelt ein Array der eindeutigen Werte für das lang-Attribut, die im allVoices-Array von Objekten gefunden werden. Beachten Sie, dass die return-Anweisung den Spread-Operator in Kombination mit einem neuen Set-Objekt verwendet, um sicherzustellen, dass das zurückgegebene Array keine Duplikate enthält. Die Funktion getPrimaryLanguages() gibt ein Array der zweibuchstabigen Ländercodes zurück. Das ergibt eine kleinere Liste nur der Hauptsprachen ohne Bezug auf regionale Dialekte.

function setUpVoices() {
  allVoices = getAllVoices();
  allLanguages = getAllLanguages(allVoices);
  primaryLanguages = getPrimaryLanguages(allLanguages);
  filterVoices();
  if (initialSetup && allVoices.length) {
    initialSetup = false;
    createLanguageMenu();
  }
}

function getAllLanguages(voices) {
  let langs = [];
  voices.forEach(vobj => {
    langs.push(vobj.lang.trim());
  });
  return [...new Set(langs)];
}

function  getPrimaryLanguages(langlist) {
  let langs = [];
  langlist.forEach(vobj => {
    langs.push(vobj.substring(0,2));
  });
  return [...new Set(langs)];
}

Die Funktion setUpVoices() ruft zwei zusätzliche Funktionen auf. Die Funktion filterVoices() holt den zweibuchstabigen Sprachcode aus dem aktuellen Wert des #languageMenu-Select-Menüs und verwendet ihn, um das allVoices-Array zu filtern und nur die verfügbaren Sprachoptionen für die gewählte Sprache zurückzugeben. Sie übergibt dieses Array dann an die Funktion createSpeakerMenu() (unverändert aus Schritt 2), die das #speakerMenu mit Optionen füllt. Dann holt filterVoices() die zu der gewählten Sprache gehörende Stichpunkt und platziert sie im Textfeld, wo sie bearbeitet oder ersetzt werden kann.

Und für den Fall, dass Chrome dieses Menü neu erstellt, wird der gespeicherte voiceIndex verwendet, um die aktuelle Auswahl wiederherzustellen. Dann verwendet die Funktion createLanguageMenu() unsere Hash-Tabellen, um die benötigten Menüoptionen für das languageMenu-select-Element zu erstellen. Die Funktion selectLanguage() wird ausgelöst, wenn der Benutzer eine Sprache auswählt. Sie löst dann filterVoices() aus und setzt das #speakerMenu so, dass die erste verfügbare Option angezeigt wird.

function filterVoices() {
  let langcode = languageMenu.value;
  voices = allVoices.filter(function (voice) {
    return langcode === "all" ? true : voice.lang.indexOf(langcode + "-") >= 0;
  });
  createSpeakerMenu(voices);
  let t = blurbs[languageMenu.options[languageMenu.selectedIndex].text];
  txtFld.value = t ? t : defaultBlurb;
  speakerMenu.selectedIndex = voiceIndex;
}

function createLanguageMenu() {
  let code = `<option selected value="all">Show All</option>`;
  let langnames = [];
  primaryLanguages.forEach(function(lobj,i) {
    langnames.push(langcodehash[lobj.substring(0,2)].name);
  });
  langnames.sort();
  langnames.forEach(function(lname,i) {
    let lcode = langhash[lname].code;
    code += `<option value=${lcode}>${lname}</option>`;
  });
  languageMenu.innerHTML = code;
}

function selectLanguage() {
  filterVoices();
  speakerMenu.selectedIndex = 0;
}

Im Abschnitt der Hilfsfunktionen des Codes unten fügen Sie den folgenden Code hinzu. Dieses generische kleine Hilfsprogramm hilft Ihnen beim nächsten Mal, wenn Sie eine Nachschlagetabelle für ein Array von Objekten erstellen müssen. In unserem Fall werden wir dies verwenden, um einfach einen Sprachcode mit seinem entsprechenden Sprachnamen und umgekehrt abzugleichen.

function getLookupTable(objectsArray, propname) {
  return objectsArray.reduce((accumulator, currentValue) => (accumulator[currentValue[propname]] = currentValue, accumulator),{});
}

Ich habe ein Array von Textphrasen hinzugefügt, die jeweils eine Übersetzung der englischen Phrase „I enjoy the traditional music of my native country“ sind. Die Sprache, in der sie angezeigt wird, entspricht der im Sprachmenü ausgewählten Sprache.

Hier sehen wir die Schönheit von UTF-8 in vollem Umfang. Oberhalb der Funktion getLanguagesTags() fügen wir den Code hinzu, der all diese übersetzten Stichpunkte generiert. Ich spreche nur Spanisch, Englisch, etwas Portugiesisch und sehr wenig Deutsch, daher muss ich darauf vertrauen, dass Google Translate genaue Übersetzungen für den Rest liefert. Wenn eine dieser Sprachen Ihre Muttersprache ist, können Sie gerne Korrekturen in den Kommentaren hinterlassen.

function createBlurbs() {
  blurbs = {
    "Arabic" : "أنا أستمتع بالموسيقى التقليدية لبلدي الأم.",
    "Chinese" : "我喜歡我祖國的傳統音樂。",
    "Czech" : "Mám rád tradiční hudbu mé rodné země.",
    "Danish" : "Jeg nyder den traditionelle musik i mit hjemland.",
    "Dutch" : "Ik geniet van de traditionele muziek van mijn geboorteland.",
    "English" : "I enjoy the traditional music of my native country.",
    "Finnish" : "Nautin kotimaassani perinteistä musiikkia.",
    "French" : "J'apprécie la musique traditionnelle de mon pays d'origine.",
    "German" : "Ich genieße die traditionelle Musik meiner Heimat.",
    "Greek" : "Απολαμβάνω την παραδοσιακή μουσική της πατρίδας μου.",
    "Hebrew" : "אני נהנה מהמוסיקה המסורתית של מולדתי.",
    "Hindi" : "मैं अपने मूल देश के पारंपरिक संगीत का आनंद लेता हूं।",
    "Hungarian" : "Élvezem az én hazám hagyományos zenéjét.",
    "Indonesian" : "Saya menikmati musik tradisional negara asal saya.",
    "Italian" : "Mi piace la musica tradizionale del mio paese natale.",
    "Japanese" : "私は母国の伝統音楽を楽しんでいます。",
    "Korean" : "나는 내 조국의 전통 음악을 즐긴다.",
    "Norwegian Bokmal" : "Jeg liker den tradisjonelle musikken i mitt hjemland.",
    "Polish" : "Lubię tradycyjną muzykę mojego kraju.",
    "Portuguese" : "Eu gosto da música tradicional do meu país natal.",
    "Romanian" : "Îmi place muzica tradițională din țara mea natală.",
    "Russian" : "Мне нравится традиционная музыка моей родной страны.",
    "Slovak" : "Mám rád tradičnú hudbu svojej rodnej krajiny.",
    "Spanish" : "Disfruto de la música tradicional de mi país natal.",
    "Swedish" : "Jag njuter av traditionell musik i mitt hemland.",
    "Thai" : "ฉันเพลิดเพลินกับดนตรีดั้งเดิมของประเทศบ้านเกิดของฉัน",
    "Turkish" : "Ülkemdeki geleneksel müzikten zevk alıyorum."
  };
}

Es gibt noch eine letzte Sache: die numerische Eingabe zur Steuerung der Wiedergabegeschwindigkeit der Sprache. Modifizieren Sie die Funktion talk(), um die Sprechgeschwindigkeit aus dem numerischen Eingabefeld zu holen, und dann sind wir fertig!

Hier ist das Endergebnis:

function talk() {
  ...// no changes except for the rateFld.value reference
  u.rate = Number(rateFld.value);
  speechSynthesis.speak(u);
}

Siehe den Pen
Polyglot: Text-to-Speech in mehreren Sprachen
von Steven Estrella (@sgestrella)
auf CodePen.

Eine reale Anwendung

Mein Interesse an dieser Technologie begann vor vielen Jahren, 1990, als ich im Rahmen meiner Dissertation einen Lehrplan mit 26 Lektionen erstellte. Er wurde mit meiner ersten Programmiersprache, HyperCard, auf einem Macintosh Plus geliefert, der über eine primitive Text-to-Speech-Funktion verfügte. Ich nutzte diese Funktion, um dem Benutzer Feedback zu geben, während er das Material durcharbeitete. In jüngerer Zeit, im Jahr 2018, erstellte ich eine kostenlose progressive Web-App namens Buenos Verbos, die spanischen Sprachschülern hilft, eine Datenbank mit 766 Verben zu durchsuchen und zu filtern. Das ausgewählte Verb wird dann vollständig konjugiert, und der Benutzer kann auf die Formen klicken, um sie sich anhören zu lassen. Möglicherweise möchten Webseiten also reden, und mit etwas Fantasie finden Sie vielleicht Gründe, sie zu ermutigen. Die Frage ist: *Was wird Ihre Website als Nächstes sagen?*