diff --git a/.classpath b/.classpath
new file mode 100644
index 00000000..a4763d1e
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index ef9aebcc..293fb087 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@
# android build output:
+bin/
+gen/
obj/
libs/
diff --git a/.project b/.project
new file mode 100644
index 00000000..f14a6c5a
--- /dev/null
+++ b/.project
@@ -0,0 +1,33 @@
+
+
+ eSpeakActivity
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/res/drawable-hdpi/ic_sysbar_quicksettings.png b/res/drawable-hdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 00000000..47b4ba23
Binary files /dev/null and b/res/drawable-hdpi/ic_sysbar_quicksettings.png differ
diff --git a/res/drawable-hdpi/ic_volume.png b/res/drawable-hdpi/ic_volume.png
new file mode 100644
index 00000000..bf538ee2
Binary files /dev/null and b/res/drawable-hdpi/ic_volume.png differ
diff --git a/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png b/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png
new file mode 100644
index 00000000..31851e19
Binary files /dev/null and b/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png differ
diff --git a/res/drawable-hdpi/ic_volume_bluetooth_in_call.png b/res/drawable-hdpi/ic_volume_bluetooth_in_call.png
new file mode 100644
index 00000000..108a9e14
Binary files /dev/null and b/res/drawable-hdpi/ic_volume_bluetooth_in_call.png differ
diff --git a/res/drawable-hdpi/ic_volume_small.png b/res/drawable-hdpi/ic_volume_small.png
new file mode 100644
index 00000000..4e9a7eae
Binary files /dev/null and b/res/drawable-hdpi/ic_volume_small.png differ
diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png
new file mode 100644
index 00000000..331e2f6f
Binary files /dev/null and b/res/drawable-hdpi/icon.png differ
diff --git a/res/drawable-hdpi/stat_sys_tether_bluetooth.png b/res/drawable-hdpi/stat_sys_tether_bluetooth.png
new file mode 100644
index 00000000..11869af2
Binary files /dev/null and b/res/drawable-hdpi/stat_sys_tether_bluetooth.png differ
diff --git a/res/drawable/icon.png b/res/drawable/icon.png
new file mode 100644
index 00000000..7b7145cc
Binary files /dev/null and b/res/drawable/icon.png differ
diff --git a/res/layout/download_voice_data.xml b/res/layout/download_voice_data.xml
new file mode 100644
index 00000000..e0611ce0
--- /dev/null
+++ b/res/layout/download_voice_data.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 00000000..b23ac2dc
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/raw/espeakdata.zip b/res/raw/espeakdata.zip
new file mode 100644
index 00000000..1571f7b6
Binary files /dev/null and b/res/raw/espeakdata.zip differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
new file mode 100644
index 00000000..58169dc4
--- /dev/null
+++ b/res/values-af/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS-instellings"
+ "Verstek toonhoogte"
+ "Stemgeslag"
+ "Spraaktempo-vermenigvuldiger"
+ "Installeer tans stemdata..."
+ "eSpeak is nie as jou verstek teks-na-spraak-enjin opgestel nie. Wil jy dit nou so stel?"
+ "eSpeak kon nie stemdata installeer nie. Kontroleer asseblief jou SD-kaart."
+ "Jammer, eSpeak kon nie begin nie. Wil jy \'n foutverslag stuur?"
+ "Kon nie eSpeak laai nie"
+ "eSpeak kon nie laai nie. Wil jy \'n verslag na die ontwikkelaar stuur?"
+ "Geen instellings beskikbaar nie"
+ "Verstek stem: %s"
+ "Stemme geïnstalleer: %d"
+ "Algemene TTS-instellings"
+ "eSpeak TTS-instellings"
+ "Laai tans, wag asseblief..."
+ "Jammer, eSpeak kon nie laai nie."
+ "Hierdie is \'n voorbeeld van gesproke teks in %s"
+
+ - "Baie laag"
+ - "Laag"
+ - "Normaal"
+ - "Hoog"
+ - "Baie hoog"
+
+
+ - "Verstek"
+ - "Manlik"
+ - "Vroulik"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
new file mode 100644
index 00000000..e03f281e
--- /dev/null
+++ b/res/values-am/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS ቅንብሮች"
+ "ነባሪ የድምጽ መውጣት/መውረድ"
+ "የድምጽ ጾታ"
+ "የንግግር መጠን ማባዣ"
+ "የድምጽ ውሂብ በመጫን ላይ…"
+ "eSpeak እንደነባሪ የጽሑፍ-ወደ-ንግግር ፕሮግራም ሆኖ አልተቀመጠም። አሁን ማስቀመጥ ትፈልጋለህ?"
+ "eSpeak የድምጽ ውሂብ መጫን አልተሳካለትም። እባክህ የማከማቻ መሳሪያ ካርድህን ፈትሽ።"
+ "ይቅርታ፣ eSpeak መጀመር አልቻለም። የስህተት ሪፖርት መላክ ትፈልጋለህ?"
+ "eSpeak በመጫን ላይ ሳለ ስህተት"
+ "eSpeak እተየጫነ ሳለ ስህተት አጋጥሞታል። ወደ ገንቢው ሪፖርት መላክ ትፈልጋለህ?"
+ "ምንም ቅንብሮች የሉም"
+ "ነባሪ ድምጽ፦ %s"
+ "የተጫኑ ድምጾች፦ %d"
+ "አጠቃላይ የ TTS ቅንብሮች"
+ "eSpeak TTS ቅንብሮች"
+ "በመጫን ላይ፣ እባክህ ጠብቅ…"
+ "ይቅርታ eSpeak መጫን አልቻለም።"
+ "ይሄ በ%s ላይ የተነገረ ጽሑፍ ናሙና ነው።"
+
+ - "በጣም የወረደ"
+ - "የወረደ"
+ - "መደበኛ"
+ - "የወጣ"
+ - "በጣም የወጣ"
+
+
+ - "ነባሪ"
+ - "ወንድ"
+ - "ሴት"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
new file mode 100644
index 00000000..8c7b630c
--- /dev/null
+++ b/res/values-ar/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "إعدادات eSpeak TTS"
+ "المستوى الافتراضي"
+ "جنس الصوت"
+ "مضاعف معدل الكلام"
+ "جارٍ تثبيت البيانات الصوتية…"
+ "لم يتم تعيين eSpeak كمحرك افتراضي لتحويل النص إلى كلام. هل تريد تعيينه الآن؟"
+ "أخفق eSpeak في تثبيت البيانات الصوتية. الرجاء التحقق من بطاقة SD."
+ "عذرًا، أخفق بدء eSpeak. هل تريد إرسال تقرير بالخطأ؟"
+ "حدث خطأ أثناء تحميل eSpeak"
+ "واجه eSpeak خطأ أثناء التحميل. هل تريد إرسال تقرير إلى مطور البرنامج؟"
+ "لا تتوفر أي إعدادات"
+ "الصوت الافتراضي: %s"
+ "الأصوات المثبتة: %d"
+ "إعدادات TTS العامة"
+ "إعدادات eSpeak TTS"
+ "جارٍ التحميل، يُرجى الانتظار..."
+ "عذرًا، أخفق تحميل eSpeak."
+ "هذه عينة من النص الذي تم نطقه في %s"
+
+ - "منخفض جدًا"
+ - "منخفض"
+ - "عادي"
+ - "عالٍ"
+ - "عالٍ جدًا"
+
+
+ - "الافتراضي"
+ - "ذكر"
+ - "أنثى"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
new file mode 100644
index 00000000..af2a9b46
--- /dev/null
+++ b/res/values-bg/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Настройки за eSpeak TTS"
+ "Височина по подразбиране"
+ "Пол на гласа"
+ "Множител на скоростта на говора"
+ "Гласовите данни се инсталират..."
+ "Не сте задали eSpeak като машината си по подразбиране за синтезиран говор. Искате ли да го направите сега?"
+ "Инсталирането на гласови данни от eSpeak не бе успешно. Моля, проверете SD картата си."
+ "За съжаление стартирането на eSpeak не бе успешно. Искате ли да изпратите сигнал за грешка?"
+ "При зареждането на eSpeak възникна грешка"
+ "При зареждането на eSpeak възникна грешка. Искате ли да изпратите сигнал до програмиста?"
+ "Няма налични настройки"
+ "Глас по подразбиране: %s"
+ "Инсталирани гласове: %d"
+ "Общи настройки за TTS"
+ "Настройки за eSpeak TTS"
+ "Зарежда се. Моля, изчакайте..."
+ "За съжаление зареждането на eSpeak не бе успешно."
+ "Това е откъс от изговорен текст на %s"
+
+ - "Много ниско"
+ - "Ниско"
+ - "Нормално"
+ - "Високо"
+ - "Много високо"
+
+
+ - "По подразбиране"
+ - "Мъжки"
+ - "Женски"
+
+
+ - "х 1"
+ - "x 2"
+ - "x 3"
+ - "х 4"
+ - "x 5"
+
+
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
new file mode 100644
index 00000000..45378d79
--- /dev/null
+++ b/res/values-ca/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Configuració d\'eSpeak TTS"
+ "To predeterminat"
+ "Gènere de veu"
+ "Multiplicador de velocitat de la veu"
+ "S\'estan instal·lant les dades de veu..."
+ "eSpeak no s\'ha definit com a motor de text a veu predeterminat. Vols definir-lo ara?"
+ "eSpeak no ha pogut instal·lar dades de veu. Comprova la targeta SD."
+ "No s\'ha pogut iniciar eSpeak. Vols enviar un informe d\'error?"
+ "S\'ha produït un error en carregar eSpeak"
+ "eSpeak ha detectat un error durant la càrrega. Vols enviar un informe al desenvolupador?"
+ "No hi ha configuracions disponibles"
+ "Veu predeterminada: %s"
+ "Veus instal·lades: %d"
+ "Configuració general de TTS"
+ "Configuració d\'eSpeak TTS"
+ "S\'està carregant; espera..."
+ "No s\'ha pogut carregar eSpeak."
+ "Aquesta és una mostra de text dit en veu alta en %s"
+
+ - "Molt baix"
+ - "Baix"
+ - "Normal"
+ - "Alt"
+ - "Molt alt"
+
+
+ - "Predeterminat"
+ - "Home"
+ - "Dona"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
new file mode 100644
index 00000000..6c5ca562
--- /dev/null
+++ b/res/values-cs/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Nastavení modulu eSpeak TTS"
+ "Výchozí výška hlasu"
+ "Pohlaví"
+ "Multiplikátor rychlosti řeči"
+ "Instalace hlasových dat..."
+ "Aplikace eSpeak není nastavena jako váš výchozí modul pro převod textu na řeč. Chcete ji nastavit nyní?"
+ "Aplikaci eSpeak se nepodařilo nainstalovat hlasová data. Zkontrolujte prosím kartu SD."
+ "Je nám líto, aplikaci eSpeak se nepodařilo spustit. Chcete odeslat zprávu o chybě?"
+ "Při načítání aplikace eSpeak došlo k chybě"
+ "Při načítání aplikace eSpeak došlo k chybě. Chcete odeslat zprávu pro vývojáře?"
+ "Žádné nastavení není k dispozici"
+ "Výchozí hlas: %s"
+ "Počet nainstalovaných hlasů: %d"
+ "Obecná nastavení modulu TTS"
+ "Nastavení modulu eSpeak TTS"
+ "Načítání, čekejte prosím..."
+ "Je nám líto, aplikaci eSpeak se nepodařilo načíst."
+ "Toto je ukázkový text namluvený v jazyce %s"
+
+ - "Velmi hluboký"
+ - "Hluboký"
+ - "Normální"
+ - "Vysoký"
+ - "Velmi vysoký"
+
+
+ - "Výchozí"
+ - "Mužský"
+ - "Ženský"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
new file mode 100644
index 00000000..dc8bc35d
--- /dev/null
+++ b/res/values-da/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak-indstillinger for TTT"
+ "Standard tonehøjde"
+ "Stemmens køn:"
+ "Talehastighedsmultiplikator"
+ "Installerer stemmedata..."
+ "eSpeak er ikke angivet som din standard tekst-til-tale-maskine. Vil du gøre det nu?"
+ "eSpeak kunne ikke installere stemmedataene. Kontrollér dit SD-kort."
+ "Vi beklager, men eSpeak kunne ikke startes. Vil du sende en fejlrapport?"
+ "Fejl ved indlæsning af eSpeak"
+ "eSpeak er stødt på en fejl under indlæsning. Vil du sende en rapport til udvikleren?"
+ "Der er ingen tilgængelige indstillinger"
+ "Standardstemme: %s"
+ "Installerede stemmer: %d"
+ "Generelle indstillinger for TTT"
+ "eSpeak-indstillinger for TTT"
+ "Indlæser. Vent et øjeblik..."
+ "Vi beklager, men eSpeak kunne ikke indlæses."
+ "Dette er et eksempel på talt tekst på %s"
+
+ - "Meget lav"
+ - "Lav"
+ - "Normal"
+ - "Høj"
+ - "Meget høj"
+
+
+ - "Standard"
+ - "Mand"
+ - "Kvinde"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 00000000..5c466bdc
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS-Einstellungen"
+ "Standard-Tonlage"
+ "Geschlecht der Stimme"
+ "Multiplikationsfaktor für Sprechgeschwindigkeit"
+ "Sprachdaten werden installiert..."
+ "eSpeak ist nicht als Ihre Standard-Text-in-Sprache-Funktion festgelegt. Möchten Sie dies jetzt einstellen?"
+ "eSpeak konnte die Sprachdaten nicht installieren. Bitte überprüfen Sie Ihre SD-Karte."
+ "eSpeak konnte leider nicht gestartet werden. Möchten Sie einen Fehlerbericht senden?"
+ "Fehler beim Laden von eSpeak"
+ "Fehler beim Laden von eSpeak. Möchten Sie eine Nachricht an den Entwickler senden?"
+ "Keine Einstellungen verfügbar"
+ "Standardstimme: %s"
+ "Installierte Stimmen: %d"
+ "Allgemeine Text-in-Sprache-Einstellungen"
+ "eSpeak TTS-Einstellungen"
+ "Ladevorgang läuft. Bitte warten..."
+ "eSpeak konnte leider nicht geladen werden."
+ "Dies ist ein Beispieltext auf %s."
+
+ - "Sehr tief"
+ - "Tief"
+ - "Normal"
+ - "Hoch"
+ - "Sehr hoch"
+
+
+ - "Standard"
+ - "Männlich"
+ - "Weiblich"
+
+
+ - "1-fach"
+ - "2-fach"
+ - "3-fach"
+ - "4-fach"
+ - "5-fach"
+
+
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
new file mode 100644
index 00000000..39b629ff
--- /dev/null
+++ b/res/values-el/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Ρυθμίσεις eSpeak TTS"
+ "Προεπιλεγμένος τόνος"
+ "Φύλο φωνής"
+ "Πολλαπλασιαστής ρυθμού ομιλίας"
+ "Εγκατάσταση δεδομένων φωνής..."
+ "Το eSpeak δεν έχει οριστεί ως η προεπιλεγμένη μηχανή μετατροπής κειμένου σε λόγο. Θέλετε να το ορίσετε τώρα;"
+ "Το eSpeak απέτυχε να εγκαταστήσει τα δεδομένα φωνής. Ελέγξτε την κάρτα SD."
+ "Λυπούμαστε, η εκκίνηση του eSpeak απέτυχε. Θέλετε να στείλετε αναφορά σφάλματος;"
+ "Σφάλμα κατά τη φόρτωση του eSpeak"
+ "Το eSpeak αντιμετώπισε ένα σφάλμα κατά τη φόρτωση. Θέλετε να στείλετε αναφορά στον προγραμματιστή;"
+ "Δεν υπάρχουν διαθέσιμες ρυθμίσεις"
+ "Προεπιλεγμένη φωνή: %s"
+ "Φωνές που έχουν εγκατασταθεί: %d"
+ "Γενικές ρυθμίσεις TTS"
+ "Ρυθμίσεις eSpeak TTS"
+ "Γίνεται φόρτωση. Περιμένετε..."
+ "Λυπούμαστε, η φόρτωση του eSpeak απέτυχε."
+ "Αυτό είναι ένα δείγμα κειμένου που εκφέρεται στα %s"
+
+ - "Πολύ χαμηλός"
+ - "Χαμηλός"
+ - "Κανονικός"
+ - "Υψηλός"
+ - "Πολύ υψηλός"
+
+
+ - "Προεπιλογή"
+ - "Άντρας"
+ - "Γυναίκα"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
new file mode 100644
index 00000000..193475af
--- /dev/null
+++ b/res/values-en-rGB/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS Settings"
+ "Default pitch"
+ "Voice gender"
+ "Speech rate multiplier"
+ "Installing voice data…"
+ "eSpeak is not set as your default text-to-speech engine. Would you like to set it now?"
+ "eSpeak failed to install voice data. Please check your SD card."
+ "Sorry, eSpeak failed to start. Would you like to send an error report?"
+ "Error loading eSpeak"
+ "eSpeak encountered an error while loading. Would you like to send a report to the developer?"
+ "No settings available"
+ "Default voice: %s"
+ "Voices installed: %d"
+ "General TTS settings"
+ "eSpeak TTS settings"
+ "Loading, please wait…"
+ "Sorry, eSpeak failed to load."
+ "This is a sample of text spoken in %s"
+
+ - "Very low"
+ - "Low"
+ - "Normal"
+ - "High"
+ - "Very high"
+
+
+ - "Default"
+ - "Male"
+ - "Female"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
new file mode 100644
index 00000000..e8c13b64
--- /dev/null
+++ b/res/values-es-rUS/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Configuración de texto a voz de eSpeak"
+ "Tono predeterminado"
+ "Género de la voz"
+ "Multiplicador de la velocidad de la voz"
+ "Instalando los datos de voz..."
+ "eSpeak no se definió como tu motor de texto a voz predeterminado. ¿Deseas definirlo ahora?"
+ "eSpeak no pudo instalar los datos de voz. Verifica tu tarjeta SD."
+ "Se produjo un error al iniciar eSpeak. ¿Deseas enviar un informe de error?"
+ "Se produjo un error al cargar eSpeak."
+ "Se produjo un error al cargar eSpeak. ¿Deseas enviar un informe al programador?"
+ "No hay parámetros de configuración disponibles"
+ "Voz predeterminada: %s"
+ "Voces instaladas: %d"
+ "Configuración general de texto a voz"
+ "Configuración de texto a voz de eSpeak"
+ "Cargando recursos, aguarda..."
+ "Se produjo un error al cargar eSpeak."
+ "Este es un ejemplo de texto hablado en %s."
+
+ - "Muy grave"
+ - "Grave"
+ - "Normal"
+ - "Agudo"
+ - "Muy agudo"
+
+
+ - "Predeterminado"
+ - "Masculino"
+ - "Femenino"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
new file mode 100644
index 00000000..e717d281
--- /dev/null
+++ b/res/values-es/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Ajustes de síntesis de voz de eSpeak"
+ "Tono predeterminado"
+ "Sexo de la voz"
+ "Multiplicador de velocidad de voz"
+ "Instalando archivos de datos de voz..."
+ "eSpeak no se ha establecido como tu motor de síntesis de voz predeterminado. ¿Quieres establecerlo ahora?"
+ "eSpeak no ha podido instalar los archivos de datos de voz. Comprueba la tarjeta SD."
+ "Error al iniciar eSpeak. ¿Quieres enviar un informe de error?"
+ "Error al cargar eSpeak"
+ "eSpeak ha detectado un error al cargarse. ¿Quieres enviar un informe al desarrollador?"
+ "No hay opciones disponibles."
+ "Voz predeterminada: %s"
+ "Voces instaladas: %d"
+ "Ajustes generales de síntesis de voz"
+ "Ajustes de síntesis de voz de eSpeak"
+ "Cargando, espera..."
+ "Error al cargar eSpeak"
+ "Esto es un ejemplo de texto hablado en %s."
+
+ - "Muy bajo"
+ - "Bajo"
+ - "Normal"
+ - "Alto"
+ - "Muy alto"
+
+
+ - "Predeterminado"
+ - "Hombre"
+ - "Mujer"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
new file mode 100644
index 00000000..97518cbd
--- /dev/null
+++ b/res/values-fa/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "تنظیمات eSpeak TTS"
+ "زیر و بمی پیشفرض"
+ "جنسیت صدا"
+ "تقویتکننده سرعت گفتگو"
+ "در حال نصب دادههای صوتی..."
+ "eSpeak اکنون بعنوان موتور پیشفرض نوشتار به گفتار شما تنظیم شده است. میخواهید اکنون آن را تنظیم کنید؟"
+ "eSpeak نتوانست دادههای صوتی را نصب کند. لطفاً کارت SD خود را بررسی کنید."
+ "متأسفیم، eSpeak شروع به کار نکرد. میخواهید یک گزارش خطا ارسال کنید؟"
+ "خطا در بارگیری eSpeak"
+ "eSpeak در حین بارگیری با خطایی مواجه شده است. میخواهید یک گزارش برای برنامهنویس ارسال کنید؟"
+ "هیچ تنظیمی موجود نیست"
+ "صدای پیشفرض: %s"
+ "صداهای نصب شده: %d"
+ "تنظیمات کلی TTS"
+ "تنظیمات eSpeak TTS"
+ "در حال بارگیری، لطفاً صبر کنید..."
+ "متأسفیم، eSpeak بارگیری نشد."
+ "این یک نمونه از نوشتار گفته شده در %s است"
+
+ - "بسیار کم"
+ - "پایین"
+ - "معمولی"
+ - "زیاد"
+ - "بسیار زیاد"
+
+
+ - "پیشفرض"
+ - "مذکر"
+ - "مؤنث"
+
+
+ - "1X"
+ - "2X"
+ - "3X"
+ - "4X"
+ - "5x"
+
+
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
new file mode 100644
index 00000000..da7c80ec
--- /dev/null
+++ b/res/values-fi/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS -asetukset"
+ "Oletusäänenkorkeus"
+ "Äänen sukupuoli"
+ "Puheen nopeuskerroin"
+ "Asennetaan äänitietoja..."
+ "eSpeakia ei ole asetettu tekstistä puheeksi -oletusmoottoriksi. Asetetaanko se oletusmoottoriksi?"
+ "Äänitietojen asentaminen eSpeakiin epäonnistui. Tarkista SD-kortti."
+ "eSpeakin käynnistäminen epäonnistui. Haluatko lähettää virheilmoituksen?"
+ "Virhe ladattaessa eSpeakia"
+ "eSpeakissa esiintyi latausvirhe. Haluatko lähettää ilmoituksen kehittäjälle?"
+ "Ei asetuksia saatavilla"
+ "Oletusääni: %s"
+ "Asennettuja ääniä: %d"
+ "Yleiset TTS-asetukset"
+ "eSpeak TTS -asetukset"
+ "Ladataan. Odota..."
+ "eSpeakin lataaminen epäonnistui."
+ "Tämä on näyte kielellä %s puhutusta tekstistä"
+
+ - "Hyvin matala"
+ - "Matala"
+ - "Normaali"
+ - "Korkea"
+ - "Hyvin korkea"
+
+
+ - "Oletus"
+ - "Mies"
+ - "Nainen"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
new file mode 100644
index 00000000..66232115
--- /dev/null
+++ b/res/values-fr/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Paramètres de synthèse vocale eSpeak"
+ "Tonalité par défaut"
+ "Sexe de la voix"
+ "Multiplicateur de la cadence"
+ "Installation des données vocales en cours…"
+ "eSpeak n\'est pas votre moteur de synthèse vocale par défaut. Voulez-vous le définir en tant que tel maintenant ?"
+ "Échec de l\'installation des données vocales par eSpeak. Veuillez vérifier votre carte SD."
+ "Désolé, impossible de lancer eSpeak. Voulez-vous envoyer un rapport d\'erreur ?"
+ "Erreur lors du chargement d\'eSpeak"
+ "Une erreur s\'est produite lors du chargement d\'eSpeak. Voulez-vous envoyer un rapport au développeur ?"
+ "Aucun paramètre disponible"
+ "Voix par défaut : %s"
+ "Voix installées : %d"
+ "Paramètres généraux de synthèse vocale"
+ "Paramètres de synthèse vocale eSpeak"
+ "Chargement en cours, veuillez patienter…"
+ "Échec du chargement d\'eSpeak."
+ "Voici un exemple de texte énoncé en %s."
+
+ - "Très grave"
+ - "Grave"
+ - "Normale"
+ - "Aiguë"
+ - "Très aiguë"
+
+
+ - "Par défaut"
+ - "Homme"
+ - "Femme"
+
+
+ - "x 1"
+ - "x 2"
+ - "x 3"
+ - "x 4"
+ - "x 5"
+
+
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
new file mode 100644
index 00000000..63249952
--- /dev/null
+++ b/res/values-hi/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS सेटिंग"
+ "डिफ़ॉल्ट पिच"
+ "ध्वनि का लिंग"
+ "वाक् दर गुणक"
+ "ध्वनि डेटा इंस्टॉल किया जा रहा है…"
+ "eSpeak आपके डिफ़ॉल्ट पाठ-से-वाक् इंजन के रूप में सेट नहीं है. क्या आप इसे अभी सेट करना चाहते हैं?"
+ "eSpeak ध्वनि डेटा इंस्टॉल करने में विफल हुआ. कृपया अपना SD कार्ड जांचें."
+ "क्षमा करें, eSpeak प्रारंभ होने में विफल हुआ. क्या आप त्रुटि रिपोर्ट भेजना चाहते हैं?"
+ "eSpeak लोड करने में त्रुटि"
+ "eSpeak को लोड करते समय कोई त्रुटि आई. क्या आप डेवलपर को रिपोर्ट भेजना चाहते हैं?"
+ "कोई सेटिंग उपलब्ध नहीं"
+ "डिफ़ॉल्ट ध्वनि: %s"
+ "इंस्टॉल की गई ध्वनियां: %d"
+ "सामान्य TTS सेटिंग"
+ "eSpeak TTS सेटिंग"
+ "लोड हो रहा है, कृपया प्रतीक्षा करें…"
+ "क्षमा करें, eSpeak प्रारंभ होने में विफल हुआ."
+ "यह %s में बोले गए पाठ का नमूना है"
+
+ - "अत्यधिक कम"
+ - "कम"
+ - "सामान्य"
+ - "उच्च"
+ - "अत्यधिक उच्च"
+
+
+ - "डिफ़ॉल्ट"
+ - "पुरुष"
+ - "महिला"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
new file mode 100644
index 00000000..a153c5a4
--- /dev/null
+++ b/res/values-hr/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "TTS postavke programa eSpeak"
+ "Zadana postavka visine tona"
+ "Spol glasa"
+ "Multiplikator brzine govora"
+ "Instaliranje glasovnih podataka..."
+ "Program eSpeak nije postavljen kao vaš zadani alat za pretvaranje teksta u govor. Želite li ga sada postaviti?"
+ "Program eSpeak nije uspio instalirati glasovne podatke. Provjerite svoju SD karticu."
+ "Žao nam je, ali pokretanje programa eSpeak nije uspjelo. Želite li poslati izvješće o pogrešci?"
+ "Pogreška pri učitavanju programa eSpeak"
+ "Tijekom učitavanja programa eSpeak došlo je do pogreške. Želite li razvojnom programeru poslati izvješće?"
+ "Nema dostupnih postavki"
+ "Zadani glas: %s"
+ "Broj instaliranih glasova: %d"
+ "Opće postavke TTS-a"
+ "TTS postavke programa eSpeak"
+ "Učitavanje. Pričekajte..."
+ "Žao nam je, ali učitavanje programa eSpeak nije uspjelo."
+ "Ovo je primjer teksta izgovorenog na %s"
+
+ - "Vrlo niski"
+ - "Niska"
+ - "Uobičajena"
+ - "Visoka"
+ - "Vrlo visoko"
+
+
+ - "Zadano"
+ - "Muško"
+ - "Ženski"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
new file mode 100644
index 00000000..862ddcce
--- /dev/null
+++ b/res/values-hu/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak -- A szövegfelismerő beállításai"
+ "Alapértelmezett hangszín"
+ "Szövegfelolvasó neme"
+ "Beszédsebesség gyorsítása"
+ "Hangadatok telepítése..."
+ "Nem az eSpeak az alapértelmezett szövegfelolvasó motor. Szeretné most beállítani?"
+ "Az eSpeak nem tudta telepíteni a hangadatokat. Ellenőrizze az SD-kártyát."
+ "Sajnos az eSpeak nem indul. Szeretne hibajelentést küldeni?"
+ "Hiba az eSpeak betöltése során"
+ "Az eSpeak hibát észlelt a betöltés során. Szeretne jelentést küldeni a fejlesztőnek?"
+ "Nincs elérhető beállítás"
+ "Alapértelmezett hang: %s"
+ "Telepített hangok: %d"
+ "Általános szövegfelolvasási beállítások"
+ "eSpeak -- A szövegfelismerő beállításai"
+ "Betöltés folyamatban -- kérjük, várjon..."
+ "Sajnos az eSpeak nem töltődött be."
+ "Ez egy %s nyelven felolvasott szöveg mintája."
+
+ - "Nagyon alacsony"
+ - "Alacsony"
+ - "Normál"
+ - "Magas"
+ - "Nagyon magas"
+
+
+ - "Alapértelmezett"
+ - "Férfi"
+ - "Nő"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
new file mode 100644
index 00000000..5525cd9b
--- /dev/null
+++ b/res/values-in/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Setelan eSpeak TTS"
+ "Tinggi nada default"
+ "Gender suara"
+ "Pengganda laju wicara"
+ "Memasang data suara..."
+ "eSpeak tidak disetel sebagai mesin text-to-speech default Anda. Apakah Anda ingin menyetelnya sekarang?"
+ "eSpeak gagal memasang data suara. Periksa kartu SD Anda."
+ "Maaf, eSpeak gagal dimulai. Apakah Anda ingin mengirim laporan kesalahan?"
+ "Kesalahan saat memuat eSpeak"
+ "eSpeak mengalami kesalahan saat memuat. Apakah Anda ingin melaporkan ke pengembang?"
+ "Tidak ada setelan yang tersedia"
+ "Suara default: %s"
+ "Suara yang dipasang: %d"
+ "Setelan TTS umum"
+ "Setelan eSpeak TTS"
+ "Memuat, harap tunggu..."
+ "Maaf, eSpeak gagal dimuat."
+ "Ini adalah contoh teks yang diucapkan di %s"
+
+ - "Sangat rendah"
+ - "Rendah"
+ - "Normal"
+ - "Tinggi"
+ - "Sangat tinggi"
+
+
+ - "Default"
+ - "Pria"
+ - "Wanita"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
new file mode 100644
index 00000000..e0507ea0
--- /dev/null
+++ b/res/values-it/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Impostazioni di sintesi vocale eSpeak"
+ "Tono predefinito"
+ "Sesso voce"
+ "Moltiplicatore di velocità voce"
+ "Installazione dati vocali..."
+ "eSpeak non è impostato come motore di sintesi vocale predefinito. Impostarlo adesso?"
+ "Installazione dei dati vocali in eSpeak non riuscita. Controlla la tua scheda SD."
+ "Spiacenti, avvio di eSpeak non riuscito. Inviare una segnalazione di errore?"
+ "Errore durante il caricamento di eSpeak"
+ "eSpeak ha rilevato un errore durante il caricamento. Inviare una segnalazione allo sviluppatore?"
+ "Nessuna impostazione disponibile"
+ "Voce predefinita: %s"
+ "Voci installate: %d"
+ "Impostazioni generali di sintesi vocale"
+ "Impostazioni di sintesi vocale eSpeak"
+ "Caricamento, attendi..."
+ "Spiacenti, caricamento di eSpeak non riuscito."
+ "Questo è un esempio di testo parlato in %s"
+
+ - "Molto basso"
+ - "Basso"
+ - "Normale"
+ - "Alto"
+ - "Molto alto"
+
+
+ - "Predefinito"
+ - "Uomo"
+ - "Donna"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
new file mode 100644
index 00000000..88b7f1c0
--- /dev/null
+++ b/res/values-iw/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "הגדרות eSpeak TTS"
+ "ברירת מחדל לגובה צליל"
+ "מין הקול"
+ "מכפיל קצב דיבור"
+ "מתקין נתוני קול..."
+ "eSpeak אינו מוגדר כמנוע ברירת המחדל שלך לתכונת טקסט לדיבור. האם אתה רוצה להגדיר אותו כעת?"
+ "התקנת נתוני הקול של eSpeak נכשלה. בדוק את כרטיס ה-SD שלך."
+ "מצטערים. הפעלת eSpeak נכשלה. האם אתה רוצה לשלוח דוח שגיאה?"
+ "שגיאה בטעינת eSpeak"
+ "אירעה שגיאה ב-eSpeak בעת הטעינה. האם אתה רוצה לשלוח דוח למפתח?"
+ "אין הגדרות זמינות"
+ "ברירת מחדל לקול: %s"
+ "קולות שהותקנו: %d"
+ "הגדרות TTS כלליות"
+ "הגדרות eSpeak TTS"
+ "טוען. המתן..."
+ "מצטערים. טעינת eSpeak נכשלה."
+ "זוהי דוגמה לקריאת טקסט ב-%s"
+
+ - "נמוך מאוד"
+ - "נמוך"
+ - "רגיל"
+ - "גבוה"
+ - "גבוה מאוד"
+
+
+ - "ברירת מחדל"
+ - "זכר"
+ - "נקבה"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 00000000..8aa23f17
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeakテキスト読み上げ設定"
+ "デフォルトの声の高さ"
+ "声の性別"
+ "音声速度"
+ "音声データをインストールしています..."
+ "eSpeakはデフォルトのテキスト読み上げエンジンに設定されていません。今すぐ設定しますか?"
+ "eSpeakで音声データをインストールできませんでした。SDカードを確認してください。"
+ "eSpeakを起動できませんでした。エラーレポートを送信しますか?"
+ "eSpeakの読み込み中にエラーが発生しました"
+ "eSpeakの読み込み中にエラーが発生しました。デベロッパーにレポートを送信しますか?"
+ "利用できる設定はありません"
+ "デフォルトの音声: %s"
+ "インストールされている音声: %d"
+ "テキスト読み上げの全般設定"
+ "eSpeakテキスト読み上げ設定"
+ "読み込んでいます。お待ちください..."
+ "eSpeakを読み込めませんでした。"
+ "%sで話すテキストサンプルです。"
+
+ - "非常に低い"
+ - "低い"
+ - "標準"
+ - "高い"
+ - "非常に高い"
+
+
+ - "デフォルト"
+ - "男性"
+ - "女性"
+
+
+ - "標準"
+ - "2倍"
+ - "3倍"
+ - "4倍"
+ - "5倍"
+
+
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
new file mode 100644
index 00000000..a5d881a4
--- /dev/null
+++ b/res/values-ko/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS 설정"
+ "기본 피치"
+ "음성 성별"
+ "음성 배속 비율"
+ "음성 데이터 설치 중..."
+ "eSpeak가 기본 TTS 엔진으로 설정되지 않았습니다. 지금 설정하시겠습니까?"
+ "eSpeak에서 음성 데이터를 설치하지 못했습니다. SD 카드를 확인하세요."
+ "죄송합니다, eSpeak를 시작할 수 없습니다. 오류를 신고하시겠습니까?"
+ "eSpeak 로딩 오류"
+ "로드하는 중에 eSpeak에 오류가 발생했습니다. 개발자에게 신고하시겠습니까?"
+ "이용 가능한 설정 없음"
+ "기본 음성: %s"
+ "음성 설치됨: %d개"
+ "일반 TTS 설정"
+ "eSpeak TTS 설정"
+ "로드 중... 잠시 기다려 주세요."
+ "죄송합니다, eSpeak를 로드하지 못했습니다."
+ "%s로 읽은 텍스트 샘플입니다."
+
+ - "매우 낮음"
+ - "낮음"
+ - "보통"
+ - "높음"
+ - "매우 높음"
+
+
+ - "기본값"
+ - "남성"
+ - "여성"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
new file mode 100644
index 00000000..a17ada78
--- /dev/null
+++ b/res/values-lt/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "„eSpeak“ TĮK nustatymai"
+ "Numatytasis garso aukštis"
+ "Balso lytis"
+ "Kalbos rodiklio koeficientas"
+ "Diegiami balso duomenys..."
+ "„eSpeak“ nenustatytas kaip numatytasis teksto į kalbą variklis. Ar norite dabar nustatyti?"
+ "„eSpeak“ nepavyko įdiegti balso duomenų. Patikrinkite SD kortelę."
+ "Apgailestaujame, bet nepavyko paleisti „eSpeak“. Ar norite siųsti klaidos pranešimą?"
+ "Įkeliant „eSpeak“ įvyko klaida"
+ "Įkeliant „eSpeak“ įvyko klaida. Ar norėtumėte siųsti pranešimą kūrėjui?"
+ "Nėra pasiekiamų nustatymų"
+ "Numatytasis balsas: %s"
+ "Įdiegta balsų: %d"
+ "Bendrieji TĮK nustatymai"
+ "„eSpeak“ TĮK nustatymai"
+ "Įkeliama, palaukite..."
+ "Apgailestaujame, bet nepavyko įkelti „eSpeak“."
+ "Tai teksto, sakomo %s, pavyzdys"
+
+ - "Labai žemas"
+ - "Žemas"
+ - "Įprastas"
+ - "Aukštas"
+ - "Labai aukštas"
+
+
+ - "Numatytasis"
+ - "Vyras"
+ - "Moteris"
+
+
+ - "1 x"
+ - "2 x"
+ - "3 x"
+ - "4 x"
+ - "5 x"
+
+
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
new file mode 100644
index 00000000..0d52955f
--- /dev/null
+++ b/res/values-lv/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak teksta pārveidošanas runā iestatījumi"
+ "Balss noklusējuma augstums"
+ "Balss īpašnieka dzimums"
+ "Runas ātruma reizinātājs"
+ "Notiek balss datu instalēšana..."
+ "Programma eSpeak nav iestatīta kā noklusējuma programma teksta pārveidošanai runā. Vai vēlaties to iestatīt tūlīt?"
+ "Programmā eSpeak neizdevās instalēt balss datus. Lūdzu, pārbaudiet SD karti."
+ "Diemžēl programmu eSpeak neizdevās palaist. Vai vēlaties nosūtīt kļūdas ziņojumu?"
+ "Ielādējot programmu eSpeak, radās kļūda."
+ "Ielādējot programmu eSpeak, radās kļūda. Vai vēlaties par to ziņot izstrādātājam?"
+ "Iestatījumi nav pieejami."
+ "Noklusējuma balss: %s"
+ "Instalētie balss dati: %d"
+ "Vispārīgie teksta pārveidošanas runā iestatījumi"
+ "eSpeak teksta pārveidošanas runā iestatījumi"
+ "Notiek ielāde. Lūdzu, uzgaidiet..."
+ "Diemžēl programmu eSpeak neizdevās ielādēt."
+ "Šis ir izrunāta teksta paraugs šādā valodā: %s."
+
+ - "Ļoti zema"
+ - "Zema"
+ - "Vidēja"
+ - "Augsta"
+ - "Ļoti augsta"
+
+
+ - "Noklusējums"
+ - "Vīrietis"
+ - "Sieviete"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
new file mode 100644
index 00000000..dee6a1b9
--- /dev/null
+++ b/res/values-ms/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Tetapan TTS eSpeak"
+ "Nada lalai"
+ "Jantina suara"
+ "Pengganda kadar ucapan"
+ "Memasang data suara..."
+ "eSpeak tidak ditetapkan sebagai enjin teks-ke-pertuturan lalai anda. Adakah anda mahu menetapkannya sekarang?"
+ "eSpeak gagal memasang data suara. Sila periksa kad SD anda."
+ "Maaf, eSpeak gagal untuk bermula. Adakah anda ingin menghantar laporan ralat?"
+ "Ralat memuatkan eSpeak"
+ "eSpeak mengalami ralat semasa dimuatkan. Adakah anda ingin menghantar laporan kepada pemaju?"
+ "Tiada tetapan tersedia"
+ "Suara lalai: %s"
+ "Suara dipasang: %d"
+ "Tetapan TTS umum"
+ "Tetapan TTS eSpeak"
+ "Memuatkan, sila tunggu..."
+ "Maaf, eSpeak gagal dimuatkan."
+ "Ini adalah sampel teks yang dilafazkan dalam %s"
+
+ - "Sangat rendah"
+ - "Rendah"
+ - "Normal"
+ - "Tinggi"
+ - "Sangat tinggi"
+
+
+ - "Lalai"
+ - "Lelaki"
+ - "Perempuan"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
new file mode 100644
index 00000000..623cfc05
--- /dev/null
+++ b/res/values-nb/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Innstillinger for eSpeak tekst-til-tale"
+ "Standard tonehøyde"
+ "Kjønn for stemmen"
+ "Multiplikator for talehastighet"
+ "Installerer taledata …"
+ "eSpeak er ikke angitt som standardmotor for tekst-til-tale. Vil du gjøre det nå?"
+ "eSpeak mislyktes i å installere taledata. Kontroller SD-kortet ditt."
+ "eSpeak startet ikke. Vil du sende en feilrapport?"
+ "Feil under innlasting av eSpeak"
+ "Det oppsto en feil under innlastingen av eSpeak. Ønsker du å sende en rapport til utvikleren?"
+ "Ingen innstillinger er tilgjengelige"
+ "Standardstemme: %s"
+ "Installerte stemmer: %d"
+ "Generelle tekst-til-tale-innstillinger"
+ "Innstillinger for eSpeak tekst-til-tale"
+ "Laster inn – vent litt …"
+ "Beklager, eSpeak ble ikke lastet inn."
+ "Dette er et teksteksempel lest opp på %s"
+
+ - "Veldig lav"
+ - "Lav"
+ - "Normal"
+ - "Høy"
+ - "Veldig høy"
+
+
+ - "Standard"
+ - "Mann"
+ - "Kvinne"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
new file mode 100644
index 00000000..ce7a9ab5
--- /dev/null
+++ b/res/values-nl/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak-instellingen voor tekst-naar-spraak"
+ "Standaard toonhoogte"
+ "Geslacht van stem"
+ "Multiplier voor spreeksnelheid"
+ "Spraakgegevens installeren..."
+ "eSpeak is niet ingesteld als uw standaardengine voor tekst-naar-spraak. Wilt u dit nu instellen?"
+ "eSpeak heeft geen stemgegevens geïnstalleerd. Controleer uw SD-kaart."
+ "eSpeak kan niet worden gestart. Wilt u een foutrapport verzenden?"
+ "Fout bij het laden van eSpeak"
+ "Er is een fout opgetreden tijdens het laden van eSpeak. Wilt u een foutrapport naar de ontwikkelaar verzenden?"
+ "Geen instellingen beschikbaar"
+ "Standaardstem: %s"
+ "Geïnstalleerde stemmen: %d"
+ "Algemene instellingen voor tekst-naar-spraak"
+ "eSpeak-instellingen voor tekst-naar-spraak"
+ "Laden, even geduld..."
+ "eSpeak kan niet worden geladen."
+ "Dit is een voorbeeld van tekst die is uitgesproken in het %s"
+
+ - "Zeer laag"
+ - "Laag"
+ - "Normaal"
+ - "Hoog"
+ - "Zeer hoog"
+
+
+ - "Standaard"
+ - "Man"
+ - "Vrouw"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
new file mode 100644
index 00000000..a0362b13
--- /dev/null
+++ b/res/values-pl/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Ustawienia zamiany tekstu na mowę eSpeak"
+ "Domyślny ton"
+ "Rodzaj głosu"
+ "Mnożnik szybkości mowy"
+ "Instalowanie danych głosowych..."
+ "eSpeak nie jest ustawiony jako domyślny mechanizm odczytywania tekstu. Czy chcesz ustawić go teraz?"
+ "Zainstalowanie danych głosowych przez eSpeak nie powiodło się. Sprawdź kartę SD."
+ "Przepraszamy, uruchomienie eSpeak nie powiodło się. Czy chcesz wysłać raport o błędach?"
+ "Błąd podczas ładowania eSpeak"
+ "Podczas ładowania eSpeak wystąpił błąd. Czy chcesz wysłać raport do programisty?"
+ "Brak dostępnych ustawień"
+ "Domyślny głos: %s"
+ "Zainstalowane głosy: %d"
+ "Ogólne ustawienia odczytywania tekstu"
+ "Ustawienia eSpeak"
+ "Wczytywanie. Czekaj..."
+ "Przepraszamy, załadowanie eSpeak nie powiodło się."
+ "To jest przykład tekstu mówionego przy ustawieniu %s"
+
+ - "Bardzo niski"
+ - "Niski"
+ - "Normalny"
+ - "Wysoki"
+ - "Bardzo wysoki"
+
+
+ - "Domyślny"
+ - "Mężczyzna"
+ - "Kobieta"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
new file mode 100644
index 00000000..dae30868
--- /dev/null
+++ b/res/values-pt-rPT/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Definições do eSpeak TTS"
+ "Tom predefinido"
+ "Género da voz"
+ "Multiplicador da taxa de voz"
+ "A instalar dados de voz..."
+ "O eSpeak não está definido como o motor de síntese de voz predefinido. Pretende configurá-lo agora?"
+ "Ocorreu uma falha ao instalar os dados de voz do eSpeak. Verifique o cartão SD."
+ "Ocorreu uma falha ao iniciar o eSpeak. Pretende enviar um relatório de erro?"
+ "Erro ao carregar o eSpeak"
+ "O eSpeak encontrou um erro ao carregar. Pretende enviar um relatório para o programador?"
+ "Sem definições disponíveis"
+ "Voz predefinida: %s"
+ "Vozes instaladas: %d"
+ "Definições gerais do TTS"
+ "Definições do eSpeak TTS"
+ "A carregar; aguarde..."
+ "Ocorreu uma falha ao carregar o eSpeak."
+ "Este é um exemplo de texto falado em %s"
+
+ - "Muito baixo"
+ - "Baixo"
+ - "Normal"
+ - "Alto"
+ - "Muito alto"
+
+
+ - "Predefinição"
+ - "Masculina"
+ - "Feminina"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
new file mode 100644
index 00000000..11b91a2e
--- /dev/null
+++ b/res/values-pt/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Configurações de TTS do eSpeak"
+ "Frequência padrão do som"
+ "Gênero para a voz"
+ "Multiplicador da taxa de fala"
+ "Instalando dados de voz..."
+ "O eSpeak não está definido como seu mecanismo padrão de conversão de texto em voz. Deseja de configurá-lo agora?"
+ "Falha ao instalar os dados de voz do eSpeak. Verifique seu cartão SD."
+ "Falha ao iniciar o eSpeak. Deseja enviar um relatório de erro?"
+ "Erro ao carregar o eSpeak"
+ "Ocorreu um erro ao carregar o eSpeak. Deseja enviar um relatório ao desenvolvedor?"
+ "Nenhuma configuração disponível"
+ "Voz padrão: %s"
+ "Vozes instaladas: %d"
+ "Configurações gerais de TTS"
+ "Configurações de TTS do eSpeak"
+ "Carregando. Aguarde…"
+ "Falha ao carregar o eSpeak."
+ "Este é um exemplo de texto falado em %s"
+
+ - "Muito baixa"
+ - "Baixa"
+ - "Normal"
+ - "Alta"
+ - "Muito alta"
+
+
+ - "Padrão"
+ - "Masculino"
+ - "Feminino"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
new file mode 100644
index 00000000..0b1bd23e
--- /dev/null
+++ b/res/values-ro/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Setări TTS eSpeak"
+ "Înălţime prestabilită"
+ "Genul vocii"
+ "Multiplicator al ritmului vorbirii"
+ "Se instalează datele vocale..."
+ "eSpeak nu este setat ca motor prestabilit de transformare a textului în vorbire. Doriţi să îl setaţi acum?"
+ "eSpeak nu a putut instala datele vocale. Verificaţi cardul SD."
+ "Ne pare rău, dar pornirea eSpeak a eşuat. Doriţi să trimiteţi un raport despre eroare?"
+ "Eroare la încărcarea eSpeak"
+ "eSpeak a întâmpinat o eroare la încărcare. Doriţi să o raportaţi dezvoltatorului?"
+ "Nu există setări disponibile"
+ "Voce prestabilită: %s"
+ "Voci instalate: %d"
+ "Setări TTS generale"
+ "Setări TTS eSpeak"
+ "Se încarcă, aşteptaţi..."
+ "Ne pare rău, dar eSpeak nu s-a putut încărca."
+ "Aceasta este o mostră de text vorbit în %s"
+
+ - "Foarte scăzută"
+ - "Redusă"
+ - "Normală"
+ - "Ridicată"
+ - "Foarte ridicată"
+
+
+ - "Prestabilit"
+ - "Masculin"
+ - "Feminin"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
new file mode 100644
index 00000000..b1654866
--- /dev/null
+++ b/res/values-ru/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Настройки eSpeak"
+ "Тон по умолчанию"
+ "Параметры голоса"
+ "Скорость речи"
+ "Загрузка голосовых данных..."
+ "Установить eSpeak в качестве синтезатора речи по умолчанию?"
+ "Не удалось загрузить голосовые данные. Проверьте SD-карту."
+ "Не удалось запустить eSpeak. Отправить отчет об ошибке?"
+ "Ошибка при загрузке eSpeak"
+ "При загрузке eSpeak произошла ошибка. Сообщить об этом разработчику?"
+ "Настройки недоступны"
+ "Язык по умолчанию: %s"
+ "Голосовых модулей: %d"
+ "Общие настройки"
+ "Настройки eSpeak"
+ "Загрузка..."
+ "Не удалось загрузить eSpeak."
+ "Так синтезатор речи озвучивает %s текст"
+
+ - "Очень низкий"
+ - "Низкий"
+ - "Средний"
+ - "Высокий"
+ - "Очень высокий"
+
+
+ - "По умолчанию"
+ - "Мужской"
+ - "Женский"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
new file mode 100644
index 00000000..370ff996
--- /dev/null
+++ b/res/values-sk/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Nastavenia modulu eSpeak TTS"
+ "Predvolená výška hlasu"
+ "Pohlavie"
+ "Násobok rýchlosti reči"
+ "Prebieha inštalácia hlasových dát..."
+ "Aplikácia eSpeak nie je nastavená ako predvolený nástroj na prevod textu na reč. Chcete ju nastaviť teraz?"
+ "Aplikácii eSpeak sa nepodarilo nainštalovať hlasové dáta. Skontrolujte kartu SD."
+ "Je nám ľúto, aplikáciu eSpeak sa nepodarilo spustiť. Chcete odoslať chybovú správu?"
+ "Pri načítavaní aplikácie eSpeak sa vyskytla chyba"
+ "Pri načítavaní aplikácie eSpeak sa vyskytla chyba. Chcete odoslať správu vývojárovi?"
+ "K dispozícii nie sú žiadne nastavenia"
+ "Predvolený hlas: %s"
+ "Počet nainštalovaných hlasov: %d"
+ "Všeobecné nastavenia modulu TTS"
+ "Nastavenia modulu eSpeak TTS"
+ "Prebieha načítavanie, čakajte prosím..."
+ "Je nám ľúto, aplikáciu eSpeak sa nepodarilo načítať."
+ "Toto je ukážkový text nahovorený v jazyku %s"
+
+ - "Veľmi hlboký"
+ - "Hlboký"
+ - "Normálny"
+ - "Vysoký"
+ - "Veľmi vysoký"
+
+
+ - "Predvolené"
+ - "Mužský"
+ - "Ženský"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
new file mode 100644
index 00000000..dbabea00
--- /dev/null
+++ b/res/values-sl/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Nastavitve pretvorbe besedila v govor v mehanizmu eSpeak"
+ "Privzeta višina tona"
+ "Spol glasu:"
+ "Množitelj hitrosti govora"
+ "Namestitev glasovnih podatkov ..."
+ "Mehanizem eSpeak ni nastavljen kot privzeti za pretvorbo besedila v govor. Ali ga želite zdaj nastaviti za privzetega?"
+ "Mehanizmu eSpeak ni uspelo namestiti glasovnih podatkov. Preverite kartico SD."
+ "Mehanizma eSpeak ni bilo mogoče zagnati. Ali želite poslati poročilo o napaki?"
+ "Napaka pri nalaganju mehanizma eSpeak"
+ "V mehanizmu eSpeak je prišlo do napake med nalaganjem. Ali želite poslati poročilo razvijalcu?"
+ "Ni razpoložljivih nastavitev"
+ "Privzeti glas: %s"
+ "Št. nameščenih glasov: %d"
+ "Splošne nastavitve pretvorbe besedila v govor"
+ "Nastavitve pretvorbe besedila v govor v mehanizmu eSpeak"
+ "Nalaganje, počakajte trenutek ..."
+ "Mehanizma eSpeak ni bilo mogoče naložiti."
+ "To je vzorec besedila, izgovorjen v %s"
+
+ - "Zelo nizek"
+ - "Nizek"
+ - "Običajen"
+ - "Visok"
+ - "Zelo visok"
+
+
+ - "Privzeto"
+ - "Moški"
+ - "Ženski"
+
+
+ - "1 x"
+ - "2 x"
+ - "3 x"
+ - "4 x"
+ - "5 x"
+
+
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
new file mode 100644
index 00000000..c99fef43
--- /dev/null
+++ b/res/values-sr/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS подешавања"
+ "Подразумевани ниво"
+ "Пол гласа"
+ "Множилац брзине говора"
+ "Инсталирање гласовних података..."
+ "eSpeak није подешен као подразумевани механизам за пребацивање текста у говор. Да ли желите да га подесите сада?"
+ "eSpeak није успео да инсталира податке о гласу. Проверите SD картицу."
+ "Жао нам је, eSpeak није покренут. Да ли желите да пошаљете извештај о грешци?"
+ "Грешка при учитавању eSpeak-а"
+ "Дошло је до грешке при учитавању eSpeak-а. Да ли желите да пошаљете извештај програмеру?"
+ "Нема доступних подешавања"
+ "Подразумевани глас: %s"
+ "Инсталирани су гласови: %d"
+ "Општа подешавања TTS-а"
+ "eSpeak TTS подешавања"
+ "Учитавање, сачекајте..."
+ "Жао нам је, eSpeak није учитан."
+ "Ово је пример текста који је изговорен на језику %s"
+
+ - "Веома низак"
+ - "Низак"
+ - "Нормалнан"
+ - "Висок"
+ - "Веома висок"
+
+
+ - "Подразумевано"
+ - "Мушки"
+ - "Женски"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
new file mode 100644
index 00000000..fa372528
--- /dev/null
+++ b/res/values-sv/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "TTS-inställningar för eSpeak"
+ "Standardinställning för tonhöjd"
+ "Kön på den som talar:"
+ "Multiplikator för talhastighet"
+ "Installerar röstdata ..."
+ "Du har inte angett eSpeak som din standardmotor för text-till-tal. Vill du göra det nu?"
+ "Det gick inte att installera röstsdata i eSpeak. Kontrollera SD-kortet."
+ "Det gick tyvärr inte att starta eSpeak. Vill du skicka en felrapport?"
+ "Fel vid inläsning av eSpeak"
+ "Ett fel uppstod när eSpeak lästes in. Vill du skicka en rapport till utvecklaren?"
+ "Det finns inga inställningar"
+ "Standardröst: %s"
+ "Installerade röster: %d"
+ "Allmänna TTS-inställningar"
+ "TTS-inställningar för eSpeak"
+ "Läser in, vänta …"
+ "Det gick tyvärr inte att läsa in eSpeak."
+ "Detta är ett textexempel som läses på %s"
+
+ - "Mycket låg"
+ - "Låg"
+ - "Normal"
+ - "Hög"
+ - "Mycket hög"
+
+
+ - "Standard"
+ - "Man"
+ - "Kvinna"
+
+
+ - "x 1"
+ - "x 2"
+ - "x 3"
+ - "x 4"
+ - "x 5"
+
+
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
new file mode 100644
index 00000000..e0a5182b
--- /dev/null
+++ b/res/values-sw/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Mipangilio ya eSpeak TTS"
+ "Sauti chaguo-msingi"
+ "Jinsia ya sauti"
+ "Kizidisha kiwango cha usemi"
+ "Inasakinisha data ya sauti..."
+ "eSpeak haijawekwa kama injini yako msingi ya maandishi-hadi-usemi. Je, ungependa kuiweka sasa?"
+ "eSpeak imeshindwa kusakinisha data ya sauti. Tafadhali kagua kadi yako ya SD."
+ "Samahani, eSpeak imeshindwa kuanza. Je, ungependa kutuma ripoti ya hitilafu?"
+ "Hitilafu ya kupakia eSpeak"
+ "eSpeak ilikumbana na hitilafu wakati wa kupakia. Je, ungependa kutuma ripoti kwa msanidi programu?"
+ "Hakuna mipangilio inayopatikana"
+ "Sauti chaguo-msingi: %s"
+ "Sauti zimesakinishwa: %d"
+ "Mipangilio ya kawaida ya TTS"
+ "Mipangilio ya eSpeak TTS"
+ "Inapakia, tafadhali subiri..."
+ "Samahani, eSpeak imeshindwa kupakia."
+ "Hii ni sampuli ya maandishi yaliyonenwa katika %s"
+
+ - "Chini sana"
+ - "Chini"
+ - "Kawaida"
+ - "Juu"
+ - "Juu sana"
+
+
+ - "Chaguo msingi"
+ - "Mwanamume"
+ - "Mwanamke"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
new file mode 100644
index 00000000..ccde3d4f
--- /dev/null
+++ b/res/values-th/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "การตั้งค่า TTS ของ eSpeak"
+ "ระดับเสียงเริ่มต้น"
+ "เพศของเสียง:"
+ "ตัวคูณความเร็วการพูด"
+ "กำลังติดตั้งข้อมูลเสียง..."
+ "eSpeak ไม่ได้ถูกกำหนดให้เป็นเครื่องมืออ่านออกเสียงข้อความเริ่มต้นของคุณ คุณต้องการกำหนดเดี๋ยวนี้หรือไม่"
+ "eSpeak ไม่สามารถติดตั้งข้อมูลเสียง โปรดตรวจสอบการ์ด SD ของคุณ"
+ "ขออภัย eSpeak ไม่สามารถเริ่มต้นทำงาน คุณต้องการส่งรายงานข้อผิดพลาดหรือไม่"
+ "เกิดข้อผิดพลาดขณะที่โหลด eSpeak"
+ "eSpeak พบข้อผิดพลาดขณะที่กำลังโหลด คุณต้องการส่งรายงานไปยังนักพัฒนาซอฟต์แวร์หรือไม่"
+ "ไม่มีการตั้งค่า"
+ "เสียงเริ่มต้น: %s"
+ "เสียงที่ติดตั้ง: %d"
+ "การตั้งค่า TTS ทั่วไป"
+ "การตั้งค่า TTS ของ eSpeak"
+ "กำลังโหลด โปรดรอสักครู่..."
+ "ขออภัย eSpeak ไม่สามารถโหลด"
+ "นี่เป็นตัวอย่างของข้อความที่พูดใน %s"
+
+ - "ต่ำมาก"
+ - "ต่ำ"
+ - "ปกติ"
+ - "สูง"
+ - "สูงมาก"
+
+
+ - "ค่าเริ่มต้น"
+ - "ชาย"
+ - "หญิง"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
new file mode 100644
index 00000000..b2b79235
--- /dev/null
+++ b/res/values-tl/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Mga Setting sa TTS ng eSpeak"
+ "Default na pitch"
+ "Kasarian ng boses"
+ "Multiplier ng rate ng pananalita"
+ "Ini-install ang data ng boses…"
+ "Hindi nakatakda ang eSpeak bilang iyong default na text-to-speech engine. Gusto mo ba itong itakda ngayon?"
+ "Nabigong mag-install ng data ng boses ang eSpeak. Pakisuri ang iyong SD card."
+ "Paumanhin, nabigong magsimula ang eSpeak. Gusto mo bang magpadala ng ulat ng error?"
+ "Error sa pag-load ng eSpeak"
+ "Nakatagpo ng isang error ang eSpeak habang naglo-load. Gusto mo bang magpadala ng ulat sa developer?"
+ "Walang available na mga setting"
+ "Default na boses: %s"
+ "Mga boses na na-install: %d"
+ "Pangkalahatang mga setting ng TTS"
+ "Mga setting ng TTS ng eSpeak"
+ "Naglo-load, mangyaring maghintay..."
+ "Paumanhin, nabigong mag-load ang eSpeak."
+ "Isa itong sample ng tekstong binibigkas sa %s"
+
+ - "Napakababa"
+ - "Mababa"
+ - "Normal"
+ - "Mataas"
+ - "Napakataas"
+
+
+ - "Default"
+ - "Lalaki"
+ - "Babae"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
new file mode 100644
index 00000000..f28c5398
--- /dev/null
+++ b/res/values-tr/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak TTS Ayarları"
+ "Varsayılan ses kalınlığı"
+ "Sesin cinsiyeti"
+ "Konuşma hızı çarpanı"
+ "Ses verileri yükleniyor..."
+ "eSpeak varsayılan metin konuşma motorunuz olarak ayarlanmadı. Şimdi ayarlamak ister misiniz?"
+ "eSpeak ses verisini yükleyemedi. Lütfen SD kartınızı kontrol edin."
+ "Maalesef, eSpeak başlatılamadı. Hata raporu göndermek ister misiniz?"
+ "eSpeak yüklenirken hata oluştu"
+ "eSpeak yüklenirken bir hatayla karşılaştı. Geliştiriciye rapor göndermek ister misiniz?"
+ "Kullanılabilir ayar yok"
+ "Varsayılan ses: %s"
+ "Yüklenen ses sayısı: %d"
+ "Genel TTS ayarları"
+ "eSpeak TTS ayarları"
+ "Yükleniyor, lütfen bekleyin..."
+ "Maalesef eSpeak yüklenemedi."
+ "Bu, %s dilinde seslendirilen örnek bir metindir"
+
+ - "Çok kalın ses"
+ - "Kalın ses"
+ - "Normal"
+ - "İnce ses"
+ - "Çok ince ses"
+
+
+ - "Varsayılan"
+ - "Erkek"
+ - "Kadın"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
new file mode 100644
index 00000000..75a3b6fb
--- /dev/null
+++ b/res/values-uk/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Налаштування TTS eSpeak"
+ "Висота звуку за умовчанням"
+ "Стать за голосом"
+ "Коефіцієнт темпу мовлення"
+ "Встановлення голосових даних..."
+ "eSpeak не встановлено як систему синтезу мовлення за умовчанням. Установити зараз?"
+ "eSpeak не вдалося встановити голосові дані. Перевірте карту SD."
+ "Не вдалося запустити eSpeak. Надіслати звіт про помилку?"
+ "Помилка завантаження eSpeak"
+ "Під час завантаження eSpeak сталася помилка. Надіслати звіт розробникові?"
+ "Немає доступних налаштувань"
+ "Мова за умовчанням: %s"
+ "Установлено голосів: %d"
+ "Загальні налаштування TTS"
+ "Налаштування TTS eSpeak"
+ "Триває завантаження. Зачекайте..."
+ "Не вдалося завантажити eSpeak."
+ "Це зразок тексту такою мовою: %s"
+
+ - "Дуже низька"
+ - "Низька"
+ - "Звичайна"
+ - "Висока"
+ - "Дуже висока"
+
+
+ - "За умовчанням"
+ - "Чоловіча"
+ - "Жіноча"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
new file mode 100644
index 00000000..dcafff75
--- /dev/null
+++ b/res/values-vi/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Cài đặt chuyển văn bản thành giọng nói eSpeak"
+ "Độ cao thấp mặc định"
+ "Giới tính của giọng nói"
+ "Bội số tốc độ đọc"
+ "Đang cài đặt dữ liệu thoại…"
+ "eSpeak chưa được thiết lập làm công cụ chuyển văn bản thành giọng nói mặc định của bạn. Bạn có muốn thiết lập bây giờ không?"
+ "eSpeak không thể cài đặt dữ liệu thoại. Vui lòng kiểm tra thẻ SD của bạn."
+ "Rất tiếc, không thể khởi động eSpeak. Bạn có muốn gửi báo cáo lỗi không?"
+ "Lỗi khi tải eSpeak"
+ "eSpeak đã gặp lỗi khi tải. Bạn có muốn gửi báo cáo tới nhà phát triển không?"
+ "Không có sẵn cài đặt nào"
+ "Giọng nói mặc định: %s"
+ "Số lượng thoại đã được cài đặt: %d"
+ "Cài đặt chung chuyển văn bản thành giọng nói"
+ "Cài đặt chuyển văn bản thành giọng nói eSpeak"
+ "Đang tải, vui lòng chờ…"
+ "Rất tiếc, eSpeak không thể tải."
+ "Đây là mẫu văn bản được đọc bằng %s"
+
+ - "Rất thấp"
+ - "Thấp"
+ - "Thường"
+ - "Cao"
+ - "Rất cao"
+
+
+ - "Mặc định"
+ - "Nam"
+ - "Nữ"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
new file mode 100644
index 00000000..bb74f6f5
--- /dev/null
+++ b/res/values-zh-rCN/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak 文字转语音 (TTS) 设置"
+ "默认声调"
+ "语音性别"
+ "语速倍数"
+ "正在安装语音数据..."
+ "未将 eSpeak 设置为文字转语音的默认引擎。要立即设置吗?"
+ "eSpeak 无法安装语音数据。请检查您的 SD 卡。"
+ "很抱歉,eSpeak 启动失败。要发送错误报告吗?"
+ "加载 eSpeak 时出错"
+ "加载 eSpeak 时出错。要向开发人员发送报告吗?"
+ "无可用设置"
+ "默认语音:%s"
+ "已安装的语音库数量:%d"
+ "文字转语音 (TTS) 常规设置"
+ "eSpeak 文字转语音 (TTS) 设置"
+ "正在加载,请稍候..."
+ "很抱歉,eSpeak 加载失败。"
+ "正在朗读的是%s的语音示例"
+
+ - "很低"
+ - "低"
+ - "正常"
+ - "高"
+ - "很高"
+
+
+ - "默认"
+ - "男"
+ - "女"
+
+
+ - "1 倍"
+ - "2 倍"
+ - "3 倍"
+ - "4 倍"
+ - "5 倍"
+
+
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
new file mode 100644
index 00000000..5d4807d7
--- /dev/null
+++ b/res/values-zh-rTW/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "eSpeak 文字轉語音設定"
+ "預設音調"
+ "語音性別"
+ "語音速率調節係數"
+ "正在安裝語音資料..."
+ "eSpeak 尚未設為您的預設文字轉語音引擎。您要立即設定嗎?"
+ "eSpeak 無法安裝語音資料。請檢查您的 SD 卡。"
+ "很抱歉,無法啟動 eSpeak。您要回報錯誤嗎?"
+ "載入 eSpeak 時發生錯誤"
+ "載入 eSpeak 時發生錯誤。您要向開發人員回報嗎?"
+ "沒有可用的設定"
+ "預設語音:%s"
+ "已安裝的語音:%d"
+ "文字轉語音一般設定"
+ "eSpeak 文字轉語音設定"
+ "載入中,請稍候..."
+ "很抱歉,無法載入 eSpeak。"
+ "這是「%s」的語音測試範例"
+
+ - "非常低"
+ - "低"
+ - "正常"
+ - "高"
+ - "非常高"
+
+
+ - "預設"
+ - "男性"
+ - "女性"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
new file mode 100644
index 00000000..63bdb27a
--- /dev/null
+++ b/res/values-zu/strings.xml
@@ -0,0 +1,41 @@
+
+
+ "Izilungiselelo ze-eSpeak TTS"
+ "Izinga lezwi olithola likhona"
+ "Ubulili bezwi"
+ "Okuphindaphinda ukushesha kwenkulumo"
+ "Ifaka idatha yezwi"
+ "I-eSpeak ayisethwanga njengenjini yombhalo-uya-enkulumweni oyithola ikhona. Ingabe ungathanda ukuyisetha njengamanje?"
+ "I-eSpeak yehlulekile ukulayisha idatha yezwi. Uyacelwa ukuthi ubheke ikhadi lakho le-SD."
+ "Uxolo, i-eSpeak yehlulekile ukuqala. Ingabe ungathanda ukuthumela umbiko wephutha?"
+ "Iphutha lokulayisha i-eSpeak"
+ "I-eSpeak ihlangabezane nenkinga ngesikhathi ilayisha. Ungathanda ukuthumelela umsunguli umbiko?"
+ "Azikho izilungiselelo ezikhona"
+ "Izwi olithola likhona: %s"
+ "Amazwi afakiwe: %d"
+ "Izilungiselelo ze-TTS ezejwayelekile"
+ "Izilungiselelo ze-eSpeak TTS"
+ "Iyalayisha, ucelwa ukuthi ulinde..."
+ "Uxolo, i-eSpeak yehlulekile ukulayisha."
+ "Lena yisampula yombhalo okhulunywa kwi %s"
+
+ - "Phansi kakhulu"
+ - "Phansi"
+ - "Okulingene"
+ - "Phezulu"
+ - "Phezulu kakhulu"
+
+
+ - "Okuthola kukhona"
+ - "Owesilisa"
+ - "Owesifazane"
+
+
+ - "1x"
+ - "2x"
+ - "3x"
+ - "4x"
+ - "5x"
+
+
diff --git a/res/values/donottranslate.xml b/res/values/donottranslate.xml
new file mode 100644
index 00000000..9e420d0d
--- /dev/null
+++ b/res/values/donottranslate.xml
@@ -0,0 +1,59 @@
+
+
+
+
+ - 50
+ - 75
+ - 100
+ - 150
+ - 200
+
+
+ - 100
+ - 200
+ - 300
+ - 400
+ - 500
+
+
+ - 0
+ - 1
+ - 2
+
+
+ haai
+ Zdravo
+ 你好
+ bok
+ ahoj
+ hallo
+ hello
+ saluton
+ hei
+ bonjour
+ hallo
+ γεια σου
+ नमस्ते
+ jo napot
+ góðan dag
+ halo
+ ciao
+ roj bahsh
+ salve
+ Zdravo
+ hallo
+ witaj
+ Olá
+ salut
+ привет
+ здраво
+ ahoj
+ hola
+ Jambo
+ hej
+ vanakkam
+ merhaba
+ xin chao
+ shwmae
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100755
index 00000000..2c9f9c35
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,131 @@
+
+
+
+
+ eSpeak TTS
+
+ eSpeak TTS Settings
+
+ Default pitch
+
+ Voice gender
+
+ Speech rate multiplier
+
+ Installing voice data…
+
+ eSpeak is not set as your default text-to-speech engine. Would you like to set it now?
+
+ eSpeak failed to install voice data. Please check your SD card.
+
+ Sorry, eSpeak failed to start. Would you like to send an error report?
+
+ Error loading eSpeak
+
+ eSpeak encountered an error while loading. Would you like to send a report to the developer?
+
+ No settings available
+
+ Default voice: %s
+
+ Voices installed: %d
+
+ General TTS settings
+
+ eSpeak TTS settings
+
+ Loading, please wait…
+
+ Sorry, eSpeak failed to load.
+
+ This is a sample of text spoken in %s
+
+
+ - Very low
+ - Low
+ - Normal
+ - High
+ - Very high
+
+
+
+ - Default
+ - Male
+ - Female
+
+
+
+ - 1x
+ - 2x
+ - 3x
+ - 4x
+ - 5x
+
+
+
\ No newline at end of file
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
new file mode 100644
index 00000000..34800476
--- /dev/null
+++ b/res/xml/preferences.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/tts_engine.xml b/res/xml/tts_engine.xml
new file mode 100644
index 00000000..7da882a1
--- /dev/null
+++ b/res/xml/tts_engine.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/src/com/googlecode/eyesfree/espeak/CheckVoiceData.java b/src/com/googlecode/eyesfree/espeak/CheckVoiceData.java
new file mode 100755
index 00000000..4ebe4a4c
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/CheckVoiceData.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.Engine;
+import android.util.Log;
+
+import com.googlecode.eyesfree.espeak.SpeechSynthesis.SynthReadyCallback;
+import com.googlecode.eyesfree.espeak.SpeechSynthesis.Voice;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+public class CheckVoiceData extends Activity {
+ private static final String TAG = "eSpeakTTS";
+
+ private static final int REQUEST_DOWNLOAD = 1;
+
+ /** Resources required for eSpeak to run correctly. */
+ private static final String[] BASE_RESOURCES = {
+ "intonations", "phondata", "phonindex", "phontab", "en_dict", "voices/en/en-us"
+ };
+
+ public static File getDataPath(Context context) {
+ return new File(context.getDir("voices", MODE_WORLD_READABLE), "espeak-data");
+ }
+
+ public static boolean hasBaseResources(Context context) {
+ final File dataPath = getDataPath(context);
+
+ for (String resource : BASE_RESOURCES) {
+ final File resourceFile = new File(dataPath, resource);
+
+ if (!resourceFile.exists()) {
+ Log.e(TAG, "Missing base resource: " + resourceFile.getPath());
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ checkForVoices(false);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_DOWNLOAD:
+ checkForVoices(true);
+ break;
+ }
+ }
+
+ private void checkForVoices(boolean attemptedInstall) {
+ final File dataPath = getDataPath(this);
+
+ ArrayList availableLanguages = new ArrayList();
+ ArrayList unavailableLanguages = new ArrayList();
+
+ if (!hasBaseResources(this)) {
+ if (!attemptedInstall) {
+ downloadVoiceData();
+ return;
+ }
+ // No base resource, can't load available voices.
+ unavailableLanguages.add(Locale.ENGLISH.toString());
+ returnResults(Engine.CHECK_VOICE_DATA_MISSING_DATA, dataPath, availableLanguages,
+ unavailableLanguages);
+ return;
+ }
+
+ final SpeechSynthesis engine = new SpeechSynthesis(this, mSynthReadyCallback);
+ final List voices = engine.getAvailableVoices();
+
+ for (Voice voice : voices) {
+ availableLanguages.add(voice.toString());
+ }
+
+ final ArrayList checkFor = getIntent().getStringArrayListExtra(
+ TextToSpeech.Engine.EXTRA_CHECK_VOICE_DATA_FOR);
+
+ if (checkFor != null && !checkFor.isEmpty()) {
+ final Set checkForSet = new HashSet(checkFor);
+
+ availableLanguages = filter(availableLanguages, checkForSet);
+ unavailableLanguages = filter(unavailableLanguages, checkForSet);
+ }
+
+ returnResults(Engine.CHECK_VOICE_DATA_PASS, dataPath, availableLanguages,
+ unavailableLanguages);
+ }
+
+ /**
+ * Launches the voice data installer.
+ */
+ private void downloadVoiceData() {
+ final Intent checkIntent = new Intent(this, DownloadVoiceData.class);
+
+ startActivityForResult(checkIntent, REQUEST_DOWNLOAD);
+ }
+
+ private void returnResults(int result, File dataPath, ArrayList availableLanguages,
+ ArrayList unavailableLanguages) {
+ final Intent returnData = new Intent();
+ returnData.putStringArrayListExtra(Engine.EXTRA_AVAILABLE_VOICES, availableLanguages);
+ returnData.putStringArrayListExtra(Engine.EXTRA_UNAVAILABLE_VOICES, unavailableLanguages);
+
+ // Don't bother returning Engine.EXTRA_VOICE_DATA_FILES,
+ // Engine.EXTRA_VOICE_DATA_FILES_INFO, or
+ // Engine.EXTRA_VOICE_DATA_ROOT_DIRECTORY
+ // because they're don't seem necessary.
+
+ setResult(result, returnData);
+ finish();
+ }
+
+ /**
+ * Filters a given array list, maintaining only elements that are in the
+ * constraint. Returns a new list containing only the filtered elements.
+ */
+ private ArrayList filter(ArrayList in, Set constraint) {
+ final ArrayList out = new ArrayList(constraint.size());
+
+ for (String s : in) {
+ if (constraint.contains(s)) {
+ out.add(s);
+ }
+ }
+
+ return out;
+ }
+
+ private final SynthReadyCallback mSynthReadyCallback = new SynthReadyCallback() {
+ @Override
+ public void onSynthDataReady(byte[] audioData) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onSynthDataComplete() {
+ // Do nothing.
+ }
+ };
+}
diff --git a/src/com/googlecode/eyesfree/espeak/DownloadVoiceData.java b/src/com/googlecode/eyesfree/espeak/DownloadVoiceData.java
new file mode 100755
index 00000000..a8a92700
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/DownloadVoiceData.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.accessibility.AccessibilityEvent;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class DownloadVoiceData extends Activity {
+ public static final String BROADCAST_LANGUAGES_UPDATED = "com.googlecode.eyesfree.espeak.LANGUAGES_UPDATED";
+
+ private static final File LEGACY_DATA = new File(
+ Environment.getExternalStorageDirectory(), "espeak-data");
+
+ private AsyncExtract mAsyncExtract;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.download_voice_data);
+
+ final File dataPath = CheckVoiceData.getDataPath(this).getParentFile();
+
+ mAsyncExtract = new AsyncExtract(this, R.raw.espeakdata, dataPath) {
+ @Override
+ protected void onPostExecute(Integer result) {
+ onLanguagesInstalled(result);
+ }
+ };
+
+ mAsyncExtract.execute();
+
+ // Send a fake accessibility event so the user knows what's going on.
+ findViewById(R.id.installing_voice_data)
+ .sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ mAsyncExtract.cancel(true);
+ }
+
+ private void onLanguagesInstalled(int resultCode) {
+ switch (resultCode) {
+ case RESULT_OK:
+ final Intent intent = new Intent(BROADCAST_LANGUAGES_UPDATED);
+ sendBroadcast(intent);
+ new AsyncCleanup().execute(LEGACY_DATA);
+ break;
+ case RESULT_CANCELED:
+ // Do nothing?
+ break;
+ }
+
+ setResult(resultCode);
+ finish();
+ }
+
+ private static void clearContents(File directory) {
+ if (!directory.exists() || !directory.isDirectory()) {
+ return;
+ }
+
+ final File[] children = directory.listFiles();
+
+ for (File child : children) {
+ if (child.isDirectory()) {
+ clearContents(child);
+ }
+
+ child.delete();
+ }
+ }
+
+ private static class AsyncCleanup extends AsyncTask {
+ @Override
+ protected Void doInBackground(File... params) {
+ for (File directory : params) {
+ clearContents(directory);
+ }
+
+ return null;
+ }
+ }
+
+ private static class AsyncExtract extends AsyncTask {
+ private final LinkedList mExtractedFiles = new LinkedList();
+
+ private final Context mContext;
+ private final int mRawResId;
+ private final File mOutput;
+
+ public AsyncExtract(Context context, int rawResId, File output) {
+ mContext = context;
+ mRawResId = rawResId;
+ mOutput = output;
+ }
+
+ @Override
+ protected Integer doInBackground(Void... params) {
+ clearContents(CheckVoiceData.getDataPath(mContext));
+
+ final InputStream stream = mContext.getResources().openRawResource(mRawResId);
+ final ZipInputStream zipStream = new ZipInputStream(new BufferedInputStream(stream));
+
+ boolean successful = false;
+
+ try {
+ extractEntries(zipStream);
+ successful = true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ zipStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (isCancelled() || !successful) {
+ removeExtractedFiles();
+ return RESULT_CANCELED;
+ }
+
+ return RESULT_OK;
+ }
+
+ private void extractEntries(ZipInputStream zipStream) throws IOException {
+ final byte[] buffer = new byte[10240];
+
+ int bytesRead;
+ ZipEntry entry;
+
+ while (!isCancelled() && ((entry = zipStream.getNextEntry()) != null)) {
+ final File outputFile = new File(mOutput, entry.getName());
+
+ mExtractedFiles.add(outputFile);
+
+ if (entry.isDirectory()) {
+ outputFile.mkdirs();
+ doChmod(outputFile);
+ continue;
+ }
+
+ // Ensure the target path exists.
+ outputFile.getParentFile().mkdirs();
+
+ final FileOutputStream outputStream = new FileOutputStream(outputFile);
+
+ while (!isCancelled() && ((bytesRead = zipStream.read(buffer)) != -1)) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ outputStream.close();
+ zipStream.closeEntry();
+
+ // Make sure the output file is readable.
+ doChmod(outputFile);
+ }
+ }
+
+ private void removeExtractedFiles() {
+ for (File extractedFile : mExtractedFiles) {
+ if (!extractedFile.isDirectory()) {
+ extractedFile.delete();
+ }
+ }
+
+ mExtractedFiles.clear();
+ }
+
+ private static void doChmod(File file) {
+ try {
+ Runtime.getRuntime().exec("/system/bin/chmod 755 " + file.getAbsolutePath());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/src/com/googlecode/eyesfree/espeak/GetSampleText.java b/src/com/googlecode/eyesfree/espeak/GetSampleText.java
new file mode 100755
index 00000000..8389eaed
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/GetSampleText.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.os.Bundle;
+import android.speech.tts.TextToSpeech;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import java.util.Locale;
+
+/*
+ * Returns the sample text string for the language requested
+ */
+public class GetSampleText extends Activity {
+ private static final String TAG = GetSampleText.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Locale locale = getLocaleFromIntent(getIntent());
+ final Resources res = getResourcesForLocale(this, locale);
+
+ String text = null;
+
+ try {
+ text = res.getString(R.string.sample_text, locale.getDisplayName(locale));
+ } catch (NotFoundException e) {
+ e.printStackTrace();
+ }
+
+ final String language = (locale == null) ? "eng" : locale.getISO3Language();
+
+ if (text != null) {
+ // Do nothing.
+ } else if (language.equals("afr")) {
+ text = getString(R.string.afr);
+ } else if (language.equals("bos")) {
+ text = getString(R.string.bos);
+ } else if (language.equals("zho")) {
+ text = getString(R.string.zho);
+ } else if (language.equals("hrv")) {
+ text = getString(R.string.hrv);
+ } else if (language.equals("ces")) {
+ text = getString(R.string.ces);
+ } else if (language.equals("nld")) {
+ text = getString(R.string.nld);
+ } else if (language.equals("eng")) {
+ text = getString(R.string.eng);
+ } else if (language.equals("epo")) {
+ text = getString(R.string.epo);
+ } else if (language.equals("fin")) {
+ text = getString(R.string.fin);
+ } else if (language.equals("fra")) {
+ text = getString(R.string.fra);
+ } else if (language.equals("deu")) {
+ text = getString(R.string.deu);
+ } else if (language.equals("ell")) {
+ text = getString(R.string.ell);
+ } else if (language.equals("hin")) {
+ text = getString(R.string.hin);
+ } else if (language.equals("hun")) {
+ text = getString(R.string.hun);
+ } else if (language.equals("isl")) {
+ text = getString(R.string.isl);
+ } else if (language.equals("ind")) {
+ text = getString(R.string.ind);
+ } else if (language.equals("ita")) {
+ text = getString(R.string.ita);
+ } else if (language.equals("kur")) {
+ text = getString(R.string.kur);
+ } else if (language.equals("lat")) {
+ text = getString(R.string.lat);
+ } else if (language.equals("mkd")) {
+ text = getString(R.string.mkd);
+ } else if (language.equals("nor")) {
+ text = getString(R.string.nor);
+ } else if (language.equals("pol")) {
+ text = getString(R.string.pol);
+ } else if (language.equals("por")) {
+ text = getString(R.string.por);
+ } else if (language.equals("ron")) {
+ text = getString(R.string.ron);
+ } else if (language.equals("rus")) {
+ text = getString(R.string.rus);
+ } else if (language.equals("srp")) {
+ text = getString(R.string.srp);
+ } else if (language.equals("slk")) {
+ text = getString(R.string.slk);
+ } else if (language.equals("spa")) {
+ text = getString(R.string.spa);
+ } else if (language.equals("swa")) {
+ text = getString(R.string.swa);
+ } else if (language.equals("swe")) {
+ text = getString(R.string.swe);
+ } else if (language.equals("tam")) {
+ text = getString(R.string.tam);
+ } else if (language.equals("tur")) {
+ text = getString(R.string.tur);
+ } else if (language.equals("vie")) {
+ text = getString(R.string.vie);
+ } else if (language.equals("cym")) {
+ text = getString(R.string.cym);
+ } else {
+ Log.e(TAG, "Missing sample text for " + language);
+ text = getString(R.string.eng);
+ }
+
+ final int result = TextToSpeech.LANG_AVAILABLE;
+ final Intent returnData = new Intent();
+ returnData.putExtra("sampleText", text);
+ setResult(result, returnData);
+ finish();
+ }
+
+ private static Locale getLocaleFromIntent(Intent intent) {
+ if (intent != null) {
+ final String language = intent.getStringExtra("language");
+
+ if (language != null) {
+ return new Locale(language);
+ }
+ }
+
+ return Locale.getDefault();
+ }
+
+ private static Resources getResourcesForLocale(Activity activity, Locale locale) {
+ final Configuration config = activity.getResources().getConfiguration();
+ config.locale = locale;
+
+ final DisplayMetrics metrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ return new Resources(activity.getAssets(), metrics, config);
+ }
+}
diff --git a/src/com/googlecode/eyesfree/espeak/SpeechSynthesis.java b/src/com/googlecode/eyesfree/espeak/SpeechSynthesis.java
new file mode 100644
index 00000000..2278b762
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/SpeechSynthesis.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.content.Context;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+public class SpeechSynthesis {
+ private static final String TAG = SpeechSynthesis.class.getSimpleName();
+
+ public static final int GENDER_MALE = 1;
+ public static final int GENDER_FEMALE = 2;
+
+ static {
+ System.loadLibrary("ttsespeak");
+
+ nativeClassInit();
+ }
+
+ private final Context mContext;
+ private final SynthReadyCallback mCallback;
+ private final String mDatapath;
+
+ private boolean mInitialized = false;
+
+ public SpeechSynthesis(Context context, SynthReadyCallback callback) {
+ // First, ensure the data directory exists, otherwise init will crash.
+ final File dataPath = CheckVoiceData.getDataPath(context);
+
+ if (!dataPath.exists()) {
+ Log.e(TAG, "Missing voice data");
+ dataPath.mkdirs();
+ }
+
+ mContext = context;
+ mCallback = callback;
+ mDatapath = dataPath.getParentFile().getPath();
+
+ attemptInit();
+ }
+
+ @Override
+ protected void finalize() {
+ nativeDestroy();
+ }
+
+ public int getSampleRate() {
+ return nativeGetSampleRate();
+ }
+
+ public int getChannelCount() {
+ return nativeGetChannelCount();
+ }
+
+ public int getAudioFormat() {
+ return nativeGetAudioFormat();
+ }
+
+ public int getBufferSizeInBytes() {
+ final int bufferSizeInMillis = nativeGetBufferSizeInMillis();
+ final int sampleRate = nativeGetSampleRate();
+ return (bufferSizeInMillis * sampleRate) / 1000;
+ }
+
+ public List getAvailableVoices() {
+ final List voices = new LinkedList();
+ final String[] results = nativeGetAvailableVoices();
+
+ for (int i = 0; i < results.length; i += 4) {
+ final String name = results[i];
+ final String identifier = results[i + 1];
+ final int gender = Integer.parseInt(results[i + 2]);
+ final int age = Integer.parseInt(results[i + 3]);
+ final Voice voice = new Voice(name, identifier, gender, age);
+
+ voices.add(voice);
+ }
+
+ return voices;
+ }
+
+ public void setVoiceByProperties(
+ String name, String languages, int gender, int age, int variant) {
+ nativeSetVoiceByProperties(name, languages, gender, age, variant);
+ }
+
+ public void setLanguage(String language, int variant) {
+ attemptInit();
+
+ nativeSetLanguage(language, variant);
+ }
+
+ public void setRate(int rate) {
+ nativeSetRate(rate);
+ }
+
+ public void setPitch(int pitch) {
+ nativeSetPitch(pitch);
+ }
+
+ public void synthesize(String text) {
+ nativeSynthesize(text);
+ }
+
+ public void stop() {
+ nativeStop();
+ }
+
+ @SuppressWarnings("unused")
+ private void nativeSynthCallback(byte[] audioData) {
+ if (mCallback == null)
+ return;
+
+ if (audioData == null) {
+ mCallback.onSynthDataComplete();
+ } else {
+ mCallback.onSynthDataReady(audioData);
+ }
+ }
+
+ private void attemptInit() {
+ if (mInitialized) {
+ return;
+ }
+
+ if (!CheckVoiceData.hasBaseResources(mContext)) {
+ Log.e(TAG, "Missing base resources");
+ return;
+ }
+
+ if (!nativeCreate(mDatapath)) {
+ Log.e(TAG, "Failed to initialize speech synthesis library");
+ return;
+ }
+
+ Log.i(TAG, "Initialized synthesis library with sample rate = " + getSampleRate());
+
+ mInitialized = true;
+ }
+
+ private int mNativeData;
+
+ private static native final boolean nativeClassInit();
+
+ private native final boolean nativeCreate(String path);
+
+ private native final boolean nativeDestroy();
+
+ private native final int nativeGetSampleRate();
+
+ private native final int nativeGetChannelCount();
+
+ private native final int nativeGetAudioFormat();
+
+ private native final int nativeGetBufferSizeInMillis();
+
+ private native final String[] nativeGetAvailableVoices();
+
+ private native final boolean nativeSetVoiceByProperties(
+ String name, String languages, int gender, int age, int variant);
+
+ private native final boolean nativeSetLanguage(String language, int variant);
+
+ private native final boolean nativeSetRate(int rate);
+
+ private native final boolean nativeSetPitch(int pitch);
+
+ private native final boolean nativeSynthesize(String text);
+
+ private native final boolean nativeStop();
+
+ public interface SynthReadyCallback {
+ void onSynthDataReady(byte[] audioData);
+
+ void onSynthDataComplete();
+ }
+
+ public class Voice {
+ public final String name;
+ public final String identifier;
+ public final int gender;
+ public final int age;
+ public final Locale locale;
+
+ public Voice(String name, String identifier, int gender, int age) {
+ this.name = name;
+ this.identifier = identifier;
+ this.gender = gender;
+ this.age = age;
+
+ locale = new Locale(name);
+ }
+
+ /**
+ * Attempts a partial match against a query locale.
+ *
+ * @param query The locale to match.
+ * @return A text-to-speech availability code. One of:
+ *
+ * - {@link TextToSpeech#LANG_NOT_SUPPORTED}
+ *
- {@link TextToSpeech#LANG_AVAILABLE}
+ *
- {@link TextToSpeech#LANG_COUNTRY_AVAILABLE}
+ *
- {@link TextToSpeech#LANG_COUNTRY_VAR_AVAILABLE}
+ *
+ */
+ public int match(Locale query) {
+ if (!locale.getISO3Language().equals(query.getISO3Language())) {
+ return TextToSpeech.LANG_NOT_SUPPORTED;
+ } else if (!locale.getISO3Country().equals(query.getISO3Country())) {
+ return TextToSpeech.LANG_AVAILABLE;
+ } else if (!locale.getVariant().equals(query.getVariant())) {
+ return TextToSpeech.LANG_COUNTRY_AVAILABLE;
+ } else {
+ return TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/src/com/googlecode/eyesfree/espeak/TtsService.java b/src/com/googlecode/eyesfree/espeak/TtsService.java
new file mode 100644
index 00000000..155905fb
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/TtsService.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.media.AudioTrack;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.speech.tts.SynthesisCallback;
+import android.speech.tts.SynthesisRequest;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeechService;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.googlecode.eyesfree.espeak.SpeechSynthesis.SynthReadyCallback;
+import com.googlecode.eyesfree.espeak.SpeechSynthesis.Voice;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Implements the eSpeak engine as a {@link TextToSpeechService}.
+ *
+ * @author alanv@google.com (Alan Viverette)
+ */
+public class TtsService extends TextToSpeechService {
+ private static final String TAG = TtsService.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private static final String DEFAULT_LANGUAGE = "en";
+ private static final String DEFAULT_COUNTRY = "uk";
+ private static final String DEFAULT_VARIANT = "";
+
+ private SpeechSynthesis mEngine;
+ private SynthesisCallback mCallback;
+
+ private List mAvailableVoices;
+
+ private String mLanguage = DEFAULT_LANGUAGE;
+ private String mCountry = DEFAULT_COUNTRY;
+ private String mVariant = DEFAULT_VARIANT;
+
+ @Override
+ public void onCreate() {
+ if (!CheckVoiceData.hasBaseResources(this)) {
+ final IntentFilter filter =
+ new IntentFilter(DownloadVoiceData.BROADCAST_LANGUAGES_UPDATED);
+ registerReceiver(mBroadcastReceiver, filter);
+
+ final Intent intent = new Intent(this, DownloadVoiceData.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+
+ return;
+ }
+
+ initializeTtsEngine();
+
+ // This calls onIsLanguageAvailable() and must run AFTER initialization!
+ super.onCreate();
+ }
+
+ /**
+ * Sets up the native eSpeak engine.
+ */
+ private void initializeTtsEngine() {
+ if (mEngine != null) {
+ mEngine.stop();
+ mEngine = null;
+ }
+
+ mEngine = new SpeechSynthesis(this, mSynthCallback);
+ mAvailableVoices = mEngine.getAvailableVoices();
+ }
+
+ @Override
+ protected String[] onGetLanguage() {
+ // This is used to specify the language requested from GetSampleText.
+ return new String[] {
+ mLanguage, mCountry, mVariant
+ };
+ }
+
+ @Override
+ protected int onIsLanguageAvailable(String language, String country, String variant) {
+ if (mAvailableVoices == null) {
+ Log.e(TAG, "Attempted to check language availability before loading voices!");
+ return TextToSpeech.LANG_NOT_SUPPORTED;
+ }
+
+ final Locale query = new Locale(language, country, variant);
+
+ boolean hasLanguage = false;
+ boolean hasCountry = false;
+
+ synchronized (mAvailableVoices) {
+ for (Voice voice : mAvailableVoices) {
+ switch (voice.match(query)) {
+ case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
+ return TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE;
+ case TextToSpeech.LANG_COUNTRY_AVAILABLE:
+ hasCountry = true;
+ case TextToSpeech.LANG_AVAILABLE:
+ hasLanguage = true;
+ break;
+ }
+ }
+ }
+
+ if (!hasLanguage) {
+ return TextToSpeech.LANG_NOT_SUPPORTED;
+ } else if (!hasCountry) {
+ return TextToSpeech.LANG_AVAILABLE;
+ } else {
+ return TextToSpeech.LANG_COUNTRY_AVAILABLE;
+ }
+
+ }
+
+ @Override
+ protected int onLoadLanguage(String language, String country, String variant) {
+ final int result = onIsLanguageAvailable(language, country, variant);
+
+ // Return immediately if the language is not available.
+ if (result != TextToSpeech.LANG_AVAILABLE && result != TextToSpeech.LANG_COUNTRY_AVAILABLE
+ && result != TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE) {
+ Log.e(TAG, "Failed to load language {language='" + language + "', country='" + country
+ + "', variant='" + variant + "'");
+ return result;
+ }
+
+ synchronized (this) {
+ mLanguage = language;
+ mCountry = ((country == null) ? "" : country);
+ mVariant = ((variant == null) ? "" : variant);
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void onStop() {
+ Log.i(TAG, "Received stop request.");
+
+ mEngine.stop();
+ }
+
+ @Override
+ protected synchronized void onSynthesizeText(
+ SynthesisRequest request, SynthesisCallback callback) {
+ final String text = request.getText();
+ final String language = getRequestLanguage(request);
+ final int gender = getDefaultGender();
+ final int rate = scaleRate(request.getSpeechRate());
+ final int pitch = scalePitch(request.getPitch());
+ final Bundle params = request.getParams();
+
+ mLanguage = request.getLanguage();
+ mCountry = request.getCountry();
+ mVariant = request.getVariant();
+
+ if (DEBUG) {
+ Log.i(TAG, "Received synthesis request: {language=\"" + language + "\"}");
+
+ for (String key : params.keySet()) {
+ Log.v(TAG,
+ "Synthesis request contained param {" + key + ", " + params.get(key) + "}");
+ }
+ }
+
+ mCallback = callback;
+ mCallback.start(mEngine.getSampleRate(), mEngine.getAudioFormat(),
+ mEngine.getChannelCount());
+
+ mEngine.setVoiceByProperties(null, language, gender, 0, 0);
+ mEngine.setRate(rate);
+ mEngine.setPitch(pitch);
+ mEngine.synthesize(text);
+ }
+
+ /**
+ * Scales the pitch by the user-specified value.
+ *
+ * @param pitch A pitch value.
+ * @return A scaled pitch value.
+ */
+ private int scalePitch(int pitch) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final String defaultPitchString = prefs.getString("default_pitch", "100");
+ final int defaultPitch = Integer.parseInt(defaultPitchString);
+
+ return (pitch * defaultPitch / 100);
+ }
+
+ /**
+ * Returns user-specified gender.
+ *
+ * @return A gender value.
+ */
+ private int getDefaultGender() {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final String defaultGenderString = prefs.getString("default_gender", "0");
+ final int defaultGender = Integer.parseInt(defaultGenderString);
+
+ return defaultGender;
+ }
+
+ /**
+ * Scales the rate by the user-specified value.
+ *
+ * @param rate A rate value.
+ * @return A scaled rate value.
+ */
+ private int scaleRate(int rate) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final String defaultRateString = prefs.getString("default_rate", "100");
+ final int defaultRate = Integer.parseInt(defaultRateString);
+
+ return (rate * defaultRate / 100);
+ }
+
+ /**
+ * Retrieves the language code from a synthesis request.
+ *
+ * @param request The synthesis request.
+ * @return A language code in the format "en-uk-n".
+ */
+ private static String getRequestLanguage(SynthesisRequest request) {
+ final StringBuffer result = new StringBuffer(request.getLanguage());
+
+ final String country = request.getCountry();
+ final String variant = request.getVariant();
+
+ if (!TextUtils.isEmpty(country)) {
+ result.append('-');
+ result.append(country);
+ }
+
+ if (!TextUtils.isEmpty(variant)) {
+ result.append('-');
+ result.append(variant);
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Pipes synthesizer output from native eSpeak to an {@link AudioTrack}.
+ */
+ private final SpeechSynthesis.SynthReadyCallback mSynthCallback = new SynthReadyCallback() {
+ @Override
+ public void onSynthDataReady(byte[] audioData) {
+ if ((audioData == null) || (audioData.length == 0)) {
+ onSynthDataComplete();
+ return;
+ }
+
+ final int maxBytesToCopy = mCallback.getMaxBufferSize();
+
+ int offset = 0;
+
+ while (offset < audioData.length) {
+ final int bytesToWrite = Math.min(maxBytesToCopy, (audioData.length - offset));
+ mCallback.audioAvailable(audioData, offset, bytesToWrite);
+ offset += bytesToWrite;
+ }
+ }
+
+ @Override
+ public void onSynthDataComplete() {
+ mCallback.done();
+ }
+ };
+
+ /**
+ * Listens for language update broadcasts and initializes the eSpeak engine.
+ */
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ initializeTtsEngine();
+ }
+ };
+}
diff --git a/src/com/googlecode/eyesfree/espeak/TtsSettingsActivity.java b/src/com/googlecode/eyesfree/espeak/TtsSettingsActivity.java
new file mode 100644
index 00000000..c11e7007
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/TtsSettingsActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+
+public class TtsSettingsActivity extends PreferenceActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.preferences);
+
+ fixListSummaries(getPreferenceScreen());
+ }
+
+ /**
+ * Since the "%s" summary is currently broken, this sets the preference
+ * change listener for all {@link ListPreference} views to fill in the
+ * summary with the current entry value.
+ */
+ private void fixListSummaries(PreferenceGroup group) {
+ if (group == null) {
+ return;
+ }
+
+ final int count = group.getPreferenceCount();
+
+ for (int i = 0; i < count; i++) {
+ final Preference preference = group.getPreference(i);
+
+ if (preference instanceof PreferenceGroup) {
+ fixListSummaries((PreferenceGroup) preference);
+ } else if (preference instanceof ListPreference) {
+ preference.setOnPreferenceChangeListener(mPreferenceChangeListener);
+ }
+ }
+ }
+
+ /**
+ * Listens for preference changes and updates the summary to reflect the
+ * current setting. This shouldn't be necessary, since preferences are
+ * supposed to automatically do this when the summary is set to "%s".
+ */
+ private final OnPreferenceChangeListener mPreferenceChangeListener =
+ new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference instanceof ListPreference && newValue instanceof String) {
+ final ListPreference listPreference = (ListPreference) preference;
+ final int index = listPreference.findIndexOfValue((String) newValue);
+ final CharSequence[] entries = listPreference.getEntries();
+
+ if (index >= 0 && index < entries.length) {
+ preference.setSummary(entries[index].toString().replaceAll("%", "%%"));
+ } else {
+ preference.setSummary("");
+ }
+ }
+
+ return true;
+ }
+ };
+}
diff --git a/src/com/googlecode/eyesfree/espeak/eSpeak.java b/src/com/googlecode/eyesfree/espeak/eSpeak.java
new file mode 100755
index 00000000..4ae49440
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/eSpeak.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/*
+ * The Java portion of this TTS plugin engine app does nothing.
+ * This activity is only here so that the native code can be
+ * wrapped up inside an apk file.
+ *
+ * The file path structure convention is that the native library
+ * implementing TTS must be a file placed here:
+ * /data/data//lib/libtts.so
+ * Example:
+ * /data/data/com.googlecode.eyesfree.espeak/lib/libttsespeak.so
+ */
+
+public class eSpeak extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // The Java portion of this does nothing.
+ // This activity is only here so that everything
+ // can be wrapped up inside an apk file.
+ finish();
+ }
+}
diff --git a/src/com/googlecode/eyesfree/espeak/eSpeakActivity.java b/src/com/googlecode/eyesfree/espeak/eSpeakActivity.java
new file mode 100644
index 00000000..5331ad52
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/eSpeakActivity.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.speech.tts.TextToSpeech;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class eSpeakActivity extends Activity {
+ private static final String ACTION_TTS_SETTINGS = "com.android.settings.TTS_SETTINGS";
+
+ /** Handler code for TTS initialization hand-off. */
+ private static final int TTS_INITIALIZED = 1;
+
+ private static final int REQUEST_CHECK = 1;
+ private static final int REQUEST_DOWNLOAD = 2;
+ private static final int REQUEST_DEFAULT = 3;
+
+ private static final int DIALOG_SET_DEFAULT = 1;
+ private static final int DIALOG_DOWNLOAD_FAILED = 2;
+ private static final int DIALOG_ERROR = 3;
+
+ private enum State {
+ LOADING,
+ FAILURE,
+ SUCCESS
+ }
+
+ private boolean mDownloadedVoiceData;
+ private ArrayList mVoices;
+ private TextToSpeech mTts;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main);
+
+ setState(State.LOADING);
+ manageSettingVisibility();
+ checkVoiceData();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ if (mTts != null) {
+ mTts.shutdown();
+ }
+ }
+
+ /**
+ * Sets the UI state.
+ *
+ * @param state The current state.
+ */
+ private void setState(State state) {
+ findViewById(R.id.loading).setVisibility((state == State.LOADING) ? View.VISIBLE
+ : View.GONE);
+ findViewById(R.id.success).setVisibility((state == State.SUCCESS) ? View.VISIBLE
+ : View.GONE);
+ findViewById(R.id.failure).setVisibility((state == State.FAILURE) ? View.VISIBLE
+ : View.GONE);
+ }
+
+ /**
+ * Launcher the voice data verifier.
+ */
+ private void checkVoiceData() {
+ final Intent checkIntent = new Intent(this, CheckVoiceData.class);
+
+ startActivityForResult(checkIntent, REQUEST_CHECK);
+ }
+
+ /**
+ * Launches the voice data installer.
+ */
+ private void downloadVoiceData() {
+ final Intent checkIntent = new Intent(this, DownloadVoiceData.class);
+
+ startActivityForResult(checkIntent, REQUEST_DOWNLOAD);
+ }
+
+ /**
+ * Initializes the TTS engine.
+ */
+ private void initializeEngine() {
+ mTts = new TextToSpeech(this, mInitListener);
+ }
+
+ /**
+ * Hides preferences according to SDK level.
+ */
+ private void manageSettingVisibility() {
+ if (Build.VERSION.SDK_INT < 14) {
+ // Hide the eSpeak setting button on pre-ICS.
+ findViewById(R.id.engineSettings).setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * Handles the result of voice data verification. If verification fails
+ * following a successful installation, displays an error dialog. Otherwise,
+ * either launches the installer or attempts to initialize the TTS engine.
+ *
+ * @param resultCode The result of voice data verification.
+ * @param data The intent containing available voices.
+ */
+ private void onDataChecked(int resultCode, Intent data) {
+ if (resultCode != TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+ if (mDownloadedVoiceData) {
+ setState(State.FAILURE);
+ showDialog(DIALOG_ERROR);
+ } else {
+ downloadVoiceData();
+ }
+ return;
+ }
+
+ mVoices = data.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
+
+ initializeEngine();
+ }
+
+ /**
+ * Handles the result of voice data installation. Either shows a failure
+ * dialog or launches the voice data verifier.
+ *
+ * @param resultCode
+ */
+ private void onDataDownloaded(int resultCode) {
+ if (resultCode != RESULT_OK) {
+ setState(State.FAILURE);
+ showDialog(DIALOG_DOWNLOAD_FAILED);
+ return;
+ }
+
+ mDownloadedVoiceData = true;
+
+ checkVoiceData();
+ }
+
+ /**
+ * Handles the result of TTS engine initialization. Either displays an error
+ * dialog or populates the activity's UI.
+ *
+ * @param status The TTS engine initialization status.
+ */
+ private void onInitialized(int status) {
+ if (!getPackageName().equals(mTts.getDefaultEngine())) {
+ showDialog(DIALOG_SET_DEFAULT);
+ return;
+ }
+
+ if (status == TextToSpeech.ERROR || mVoices == null) {
+ setState(State.FAILURE);
+ showDialog(DIALOG_ERROR);
+ return;
+ }
+
+ final Locale ttsLocale = mTts.getLanguage();
+ final String localeText = getString(
+ R.string.current_tts_locale, ttsLocale.getDisplayName());
+ final TextView currentLocale = (TextView) findViewById(R.id.currentLocale);
+ currentLocale.setText(localeText);
+
+ final String voicesText = getString(R.string.available_voices, mVoices.size());
+ final TextView availableVoices = (TextView) findViewById(R.id.availableVoices);
+ availableVoices.setText(voicesText);
+
+ findViewById(R.id.ttsSettings).setOnClickListener(mOnClickListener);
+ findViewById(R.id.engineSettings).setOnClickListener(mOnClickListener);
+
+ setState(State.SUCCESS);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_CHECK:
+ onDataChecked(resultCode, data);
+ break;
+ case REQUEST_DOWNLOAD:
+ onDataDownloaded(resultCode);
+ break;
+ case REQUEST_DEFAULT:
+ initializeEngine();
+ break;
+ }
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG_SET_DEFAULT:
+ return new AlertDialog.Builder(this).setTitle(R.string.app_name)
+ .setMessage(R.string.set_default_message)
+ .setNegativeButton(android.R.string.no, mFinishClickListener)
+ .setPositiveButton(android.R.string.ok, mDialogClickListener).create();
+ case DIALOG_DOWNLOAD_FAILED:
+ return new AlertDialog.Builder(this).setTitle(R.string.app_name)
+ .setMessage(R.string.voice_data_failed_message)
+ .setNegativeButton(android.R.string.ok, mFinishClickListener)
+ .setOnCancelListener(mFinishCancelListener).create();
+ case DIALOG_ERROR:
+ return new AlertDialog.Builder(this).setTitle(R.string.app_name)
+ .setMessage(R.string.error_message)
+ .setNegativeButton(android.R.string.no, mFinishClickListener)
+ .setNegativeButton(android.R.string.ok, mReportClickListener)
+ .setOnCancelListener(mFinishCancelListener).create();
+ }
+
+ return super.onCreateDialog(id);
+ }
+
+ private final DialogInterface.OnClickListener mDialogClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ startActivityForResult(
+ new Intent(ACTION_TTS_SETTINGS), REQUEST_DEFAULT);
+ break;
+ }
+ }
+ };
+
+ private final DialogInterface.OnClickListener mReportClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // TODO: Send a crash report.
+ finish();
+ }
+ };
+
+ private final DialogInterface.OnClickListener mFinishClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ };
+
+ private final DialogInterface.OnCancelListener mFinishCancelListener = new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ };
+
+ private final TextToSpeech.OnInitListener mInitListener = new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ mHandler.obtainMessage(TTS_INITIALIZED, status, 0).sendToTarget();
+ }
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case TTS_INITIALIZED:
+ onInitialized(msg.arg1);
+ break;
+ }
+ }
+ };
+
+ private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.engineSettings:
+ startActivityForResult(
+ new Intent(eSpeakActivity.this, TtsSettingsActivity.class),
+ REQUEST_DEFAULT);
+ break;
+ case R.id.ttsSettings:
+ startActivityForResult(new Intent(ACTION_TTS_SETTINGS), REQUEST_DEFAULT);
+ break;
+ }
+ }
+ };
+}
diff --git a/src/com/googlecode/eyesfree/espeak/providers/SettingsProvider.java b/src/com/googlecode/eyesfree/espeak/providers/SettingsProvider.java
new file mode 100644
index 00000000..2a1b98c8
--- /dev/null
+++ b/src/com/googlecode/eyesfree/espeak/providers/SettingsProvider.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.eyesfree.espeak.providers;
+
+import com.googlecode.eyesfree.espeak.CheckVoiceData;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import java.io.File;
+
+/**
+ * Provides the "engineConfig" parameter for the legacy (pre-ICS) TTS API.
+ *
+ * @author alanv@google.com (Alan Viverette)
+ */
+public class SettingsProvider extends ContentProvider {
+ private class SettingsCursor extends MatrixCursor {
+ private String settings;
+
+ public SettingsCursor(String[] columnNames) {
+ super(columnNames);
+ }
+
+ public void putSettings(String settings) {
+ this.settings = settings;
+ }
+
+ @Override
+ public int getCount() {
+ return 1;
+ }
+
+ @Override
+ public String getString(int column) {
+ return settings;
+ }
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ final File dataPath = CheckVoiceData.getDataPath(getContext());
+ final String[] dummyColumns = {
+ "", ""
+ };
+ final SettingsCursor cursor = new SettingsCursor(dummyColumns);
+ cursor.putSettings(dataPath.getParent());
+ return cursor;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}