1// ported from VoiceHistory.kt and EmotionManager.kt 2 3const VOICES = [ 4 // UK 5 { name: "Michael", id: "michael", image: "img/voices/d1.png", voiceLang: "en-GB", voiceModel: "simba-english" }, 6 { name: "Harper", id: "harper", image: "img/voices/grl2.jpg", voiceLang: "en-GB", voiceModel: "simba-english" }, 7 { name: "Freddie", id: "freddie", image: "img/voices/d2.png", voiceLang: "en-GB", voiceModel: "simba-english" }, 8 { name: "Archie", id: "archie", image: "img/voices/v10.png", voiceLang: "en-GB", voiceModel: "simba-english" }, 9 { name: "Beverly", id: "beverly", image: "img/voices/grl.jpg", voiceLang: "en-GB", voiceModel: "simba-english" }, 10 { name: "Carol", id: "carol", image: "img/voices/v6.png", voiceLang: "en-GB", voiceModel: "simba-english" }, 11 { name: "Declan", id: "ron", image: "img/voices/d3.png", voiceLang: "en-GB", voiceModel: "simba-english" }, 12 13 // Nigeria-Eng 14 { name: "Elijah", id: "elijah", image: "img/voices/v4.png", voiceLang: "en-NG", voiceModel: "simba-multilingual" }, 15 16 // Russia 17 { name: "Mikhail", id: "mikhail", image: "img/voices/v4.png", voiceLang: "ru-RU", voiceModel: "simba-multilingual" }, 18 { name: "Olga", id: "olga", image: "img/voices/grl.jpg", voiceLang: "ru-RU", voiceModel: "simba-multilingual" }, 19 { name: "Natalia", id: "natalia", image: "img/voices/grl.jpg", voiceLang: "ru-RU", voiceModel: "simba-multilingual" }, 20 { name: "Vladislav", id: "vladislav", image: "img/voices/v2.png", voiceLang: "ru-RU", voiceModel: "simba-multilingual" }, 21 { name: "Sergey", id: "sergey", image: "img/voices/d2.png", voiceLang: "ru-RU", voiceModel: "simba-multilingual" }, 22 23 // Japanese 24 { name: "Ryota", id: "ryota", image: "img/voices/v4.png", voiceLang: "ja-JP", voiceModel: "simba-multilingual" }, 25 { name: "Hina", id: "hina", image: "img/voices/grl.jpg", voiceLang: "ja-JP", voiceModel: "simba-multilingual" }, 26 { name: "Sakura", id: "sakura", image: "img/voices/grl.jpg", voiceLang: "ja-JP", voiceModel: "simba-multilingual" }, 27 { name: "Tsubasa", id: "tsubasa", image: "img/voices/v2.png", voiceLang: "ja-JP", voiceModel: "simba-multilingual" }, 28 { name: "Yuto", id: "yuto", image: "img/voices/d2.png", voiceLang: "ja-JP", voiceModel: "simba-multilingual" }, 29 30 // Chinese 31 { name: "Chun-Kit", id: "chun-kit", image: "img/voices/v4.png", voiceLang: "zh-CN", voiceModel: "simba-multilingual" }, 32 { name: "Hiu-Ching", id: "hiu-ching", image: "img/voices/grl.jpg", voiceLang: "zh-CN", voiceModel: "simba-multilingual" }, 33 { name: "Yan-Ting", id: "yan-ting", image: "img/voices/grl.jpg", voiceLang: "zh-CN", voiceModel: "simba-multilingual" }, 34 { name: "Tak-Wah", id: "tak-wah", image: "img/voices/v2.png", voiceLang: "zh-CN", voiceModel: "simba-multilingual" }, 35 { name: "Chun-Wah", id: "chun-wah", image: "img/voices/d2.png", voiceLang: "zh-CN", voiceModel: "simba-multilingual" }, 36 37 // Hindi 38 { name: "Hemant", id: "hemant", image: "img/voices/v4.png", voiceLang: "hi-IN", voiceModel: "simba-multilingual" }, 39 { name: "Priya", id: "priya", image: "img/voices/grl.jpg", voiceLang: "hi-IN", voiceModel: "simba-multilingual" }, 40 { name: "Jyoti", id: "jyoti", image: "img/voices/grl.jpg", voiceLang: "hi-IN", voiceModel: "simba-multilingual" }, 41 { name: "Sajid", id: "sajid", image: "img/voices/v2.png", voiceLang: "hi-IN", voiceModel: "simba-multilingual" }, 42 { name: "Suraj", id: "suraj", image: "img/voices/d2.png", voiceLang: "hi-IN", voiceModel: "simba-multilingual" }, 43 44 // Swedish 45 { name: "Ebba", id: "ebba", image: "img/voices/v7.png", voiceLang: "sv-SE", voiceModel: "simba-multilingual" }, 46 { name: "Axel", id: "axel", image: "img/voices/v10.png", voiceLang: "sv-SE", voiceModel: "simba-multilingual" }, 47 48 // Italian 49 { name: "Alessia", id: "alessia", image: "img/voices/v6.png", voiceLang: "it-IT", voiceModel: "simba-multilingual" }, 50 { name: "Lazzaro", id: "lazzaro", image: "img/voices/v9.png", voiceLang: "it-IT", voiceModel: "simba-multilingual" }, 51 52 // Greek 53 { name: "Eleni", id: "eleni", image: "img/voices/v5.png", voiceLang: "el-GR", voiceModel: "simba-multilingual" }, 54 { name: "Kostas", id: "kostas", image: "img/voices/v8.png", voiceLang: "el-GR", voiceModel: "simba-multilingual" }, 55 56 // Turkish 57 { name: "Elif", id: "elif", image: "img/voices/v4.png", voiceLang: "tr-TR", voiceModel: "simba-multilingual" }, 58 { name: "Yusuf", id: "yusuf", image: "img/voices/v3.png", voiceLang: "tr-TR", voiceModel: "simba-multilingual" }, 59 60 // German 61 { name: "Saskia", id: "saskia", image: "img/voices/v4.png", voiceLang: "de-DE", voiceModel: "simba-multilingual" }, 62 { name: "Lotte", id: "lotte", image: "img/voices/grl.jpg", voiceLang: "de-DE", voiceModel: "simba-multilingual" }, 63 { name: "Andra", id: "andra", image: "img/voices/v1.png", voiceLang: "de-DE", voiceModel: "simba-multilingual" }, 64 { name: "Frederick", id: "frederick", image: "img/voices/v2.png", voiceLang: "de-DE", voiceModel: "simba-multilingual" }, 65 { name: "Daan", id: "daan", image: "img/voices/d2.png", voiceLang: "de-DE", voiceModel: "simba-multilingual" }, 66 67 // French 68 { name: "Camille", id: "camille", image: "img/voices/v1.png", voiceLang: "fr-FR", voiceModel: "simba-multilingual" }, 69 { name: "Ãlise", id: "elise", image: "img/voices/grl.jpg", voiceLang: "fr-FR", voiceModel: "simba-multilingual" }, 70 { name: "Jules", id: "jules", image: "img/voices/d3.png", voiceLang: "fr-FR", voiceModel: "simba-multilingual" }, 71 { name: "Angele", id: "angele", image: "img/voices/grl2.jpg", voiceLang: "fr-FR", voiceModel: "simba-multilingual" }, 72 73 // Portuguese 74 { name: "Paulo", id: "paulo", image: "img/voices/v3.png", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 75 { name: "Bruno", id: "bruno", image: "img/voices/d2.png", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 76 { name: "Friedrich", id: "friedrich", image: "img/voices/d3.png", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 77 { name: "SÃlvia", id: "silvia", image: "img/voices/v4.png", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 78 { name: "Luiza", id: "luiza", image: "img/voices/grl2.jpg", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 79 { name: "Estela", id: "estela", image: "img/voices/rl3.jpg", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 80 { name: "Paulo", id: "paulo", image: "img/voices/d1.png", voiceLang: "pt-BR", voiceModel: "simba-multilingual" }, 81 82 // Spanish 83 { name: "Valeria", id: "valeria", image: "img/voices/g4.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 84 { name: "Pablo", id: "juan-pablo", image: "img/voices/d2.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 85 { name: "MatÃas", id: "matias", image: "img/voices/d3.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 86 { name: "Diego", id: "carlos", image: "img/voices/d1.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 87 { name: "Carmen", id: "carmen", image: "img/voices/v4.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 88 { name: "Celia", id: "celia", image: "img/voices/grl2.jpg", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 89 { name: "Romina", id: "romina", image: "img/voices/v5.png", voiceLang: "es-ES", voiceModel: "simba-multilingual" }, 90 91 // English (US) 92 { name: "Marty", id: "marty", image: "img/voices/d1.png", voiceLang: "en", voiceModel: "simba-english" }, 93 { name: "Carly", id: "carly", image: "img/voices/grl2.jpg", voiceLang: "en", voiceModel: "simba-english" }, 94 { name: "Benjamin", id: "benjamin", image: "img/voices/ismail.webp", voiceLang: "en", voiceModel: "simba-english" }, 95 { name: "Carol", id: "carol", image: "img/voices/grl.jpg", voiceLang: "en", voiceModel: "simba-english" }, 96 97 // Arabic 98 { name: "Aicha", id: "aicha", image: "img/voices/aicha.webp", voiceLang: "ar-AE", voiceModel: "simba-multilingual" }, 99 { name: "Ismail", id: "ismail", image: "img/voices/ismail.webp", voiceLang: "ar-AE", voiceModel: "simba-multilingual" } 100]; 101 102const EMOTIONS = [ 103 { 104 id: "angry", emoji: "ð ", 105 labels: { ar: "غاضب", en: "Angry", es: "Enojado", fr: "En colère", pt: "Bravo", de: "Wütend", tr: "Kızgın", sv: "Arg", el: "ÎÏ Î¼ÏμÎνοÏ", it: "Arrabbiato", ru: "СеÑдиÑÑй", zh: "çæ°", ja: "æã£ã¦ãã", hi: "à¤à¥à¤¸à¥à¤¸à¥ मà¥à¤" } 106 }, 107 { 108 id: "cheerful", emoji: "ð", 109 labels: { ar: "Ù Ø¨ØªÙØ¬", en: "Cheerful", es: "Alegre", fr: "Joyeux", pt: "Alegre", de: "Fröhlich", tr: "NeÅeli", sv: "Glad", el: "ΧαÏοÏμενοÏ", it: "Allegro", ru: "ÐеÑÑлÑй", zh: "å¼å¿", ja: "齿°ãª", hi: "à¤à¥à¤¶" } 110 }, 111 { 112 id: "sad", emoji: "ð¢", 113 labels: { ar: "ØØ²ÙÙ", en: "Sad", es: "Triste", fr: "Triste", pt: "Triste", de: "Traurig", tr: "Ãzgün", sv: "Ledsen", el: "ÎÏ ÏημÎνοÏ", it: "Triste", ru: "ÐÑÑÑÑнÑй", zh: "é¾è¿", ja: "æ²ãã", hi: "दà¥à¤à¥" } 114 }, 115 { 116 id: "terrified", emoji: "ð±", 117 labels: { ar: "Ù Ø±Ø¹ÙØ¨", en: "Terrified", es: "Aterrorizado", fr: "Terrifié", pt: "Aterrorizado", de: "Entsetzt", tr: "DehÅete düÅmüÅ", sv: "Förskräckt", el: "ΤÏομοκÏαÏημÎνοÏ", it: "Terrificato", ru: "УжаÑнÑй", zh: "ååäº", ja: "ææãã", hi: "डर à¤à¤¯à¤¾" } 118 }, 119 { 120 id: "relaxed", emoji: "ð", 121 labels: { ar: "٠رتاØ", en: "Relaxed", es: "Relajado", fr: "Détendu", pt: "Relaxado", de: "Entspannt", tr: "Rahat", sv: "Avslappnad", el: "ΧαλαÏÏÏ", it: "Rilassato", ru: "РаÑÑлабленнÑй", zh: "æ¾æ¾", ja: "ãªã©ãã¯ã¹ãã", hi: "à¤à¤°à¤¾à¤®à¤¦à¤¾à¤¯à¤" } 122 }, 123 { 124 id: "fearful", emoji: "ð¨", 125 labels: { ar: "خائÙ", en: "Fearful", es: "Temeroso", fr: "Craintif", pt: "Medroso", de: "Ãngstlich", tr: "KorkmuÅ", sv: "Räd
125d", el: "ΦοβιÏμÎνοÏ", it: "Pauroso", ru: "ÐÑпÑганнÑй", zh: "害æ", ja: "æãã¦ãã", hi: "डरा हà¥à¤" } 126 }, 127 { 128 id: "surprised", emoji: "ð²", 129 labels: { ar: "Ù ÙØ¯ÙØ´", en: "Surprised", es: "Sorprendido", fr: "Surpris", pt: "Surpreso", de: "Ãberrascht", tr: "ÅaÅkın", sv: "FörvÃ¥nad", el: "ÎκÏληκÏοÏ", it: "Sorpreso", ru: "УдивлÑннÑй", zh: "æè®¶", ja: "é©ãã", hi: "à¤à¤¶à¥à¤à¤°à¥à¤¯à¤à¤à¤¿à¤¤" } 130 }, 131 { 132 id: "calm", emoji: "ð", 133 labels: { ar: "ÙØ§Ø¯Ø¦", en: "Calm", es: "Calmado", fr: "Calme", pt: "Calmo", de: "Ruhig", tr: "Sakin", sv: "Lugn", el: "ÎÏεμοÏ", it: "Calmo", ru: "СпокойнÑй", zh: "å·é", ja: "è½ã¡çãã", hi: "शाà¤à¤¤" } 134 }, 135 { 136 id: "assertive", emoji: "ð", 137 labels: { ar: "ØØ§Ø²Ù ", en: "Assertive", es: "Decidido", fr: "Assuré", pt: "Assertivo", de: "Durchsetzungsfähig", tr: "Kararlı", sv: "Självsäker", el: "ÎÏ ÏοÏεÏοίθηÏη", it: "Assertivo", ru: "ÐапоÑиÑÑÑй", zh: "åå®", ja: "æå®ç", hi: "दà¥à¤¢à¤¼" } 138 }, 139 { 140 id: "energetic", emoji: "â¡ï¸", 141 labels: { ar: "ÙØ´ÙØ·", en: "Energetic", es: "Enérgico", fr: "Ãnergique", pt: "Energético", de: "Energisch", tr: "Enerjik", sv: "Energetisk", el: "ÎνεÏγηÏικÏÏ", it: "Energetico", ru: "ÐнеÑгиÑнÑй", zh: "ææ´»å", ja: "å æ°ãª", hi: "à¤à¤°à¥à¤à¤¾à¤µà¤¾à¤¨" } 142 }, 143 { 144 id: "warm", emoji: "â¤ï¸", 145 labels: { ar: "Ø¯Ø§ÙØ¦", en: "Warm", es: "Cálido", fr: "Chaleureux", pt: "Acolhedor", de: "Warm", tr: "Sıcak", sv: "Varm", el: "ÎεÏÏÏÏ", it: "Caldo", ru: "ТÑплÑй", zh: "温æ", ja: "温ãã", hi: "à¤à¤°à¤®à¤à¥à¤¶à¥" } 146 }, 147 { 148 id: "direct", emoji: "â¡ï¸", 149 labels: { ar: "٠باشر", en: "Direct", es: "Directo", fr: "Direct", pt: "Direto", de: "Direkt", tr: "DoÄrudan", sv: "Direkt", el: "ÎμεÏοÏ", it: "Diretto", ru: "ÐÑÑмой", zh: "ç´æ¥", ja: "ç´æ¥ç", hi: "सà¥à¤§à¤¾" } 150 }, 151 { 152 id: "bright", emoji: "âï¸", 153 labels: { ar: "٠شرÙ", en: "Bright", es: "Brillante", fr: "Brillant", pt: "Brilhante", de: "Heller", tr: "Parlak", sv: "Ljus", el: "ΦÏÏεινÏÏ", it: "Luminoso", ru: "ЯÑкий", zh: "æäº®", ja: "æãã", hi: "à¤à¤à¥à¤à¥à¤µà¤²" } 154 } 155]; 156 157const TRANSLATIONS = { 158 add_voice: { 159 ar: "+ Ø£Ø¶Ù ØµÙØªÙ", 160 en: "+ Add Your Voice", 161 es: "+ Añadir tu voz", 162 fr: "+ Ajoutez votre voix", 163 pt: "+ Adicione sua voz", 164 de: "+ Ihre Stimme hinzufügen", 165 tr: "+ Sesini ekle", 166 sv: "+ Lägg till din röst", 167 el: "+ Î ÏοÏθÎÏÏε Ïη ÏÏνή ÏαÏ", 168 it: "+ Aggiungi la tua voce", 169 ru: "+ ÐобавиÑÑ Ñвой голоÑ", 170 zh: "+ æ·»å ä½ ç声é³", 171 ja: "+ ããªãã®å£°ã追å ", 172 hi: "+ ठपनॠà¤à¤µà¤¾à¤à¤¼ à¤à¥à¤¡à¤¼à¥à¤" 173 }, 174 clone_voice: { 175 ar: "Ø§Ø³ØªÙØ³Ø§Ø® ØµÙØªÙ Ø§ÙØ¢Ù", 176 en: "Clone your voice now", 177 es: "Clona tu voz ahora", 178 fr: "Clonez votre voix maintenant", 179 pt: "Clone sua voz agora", 180 de: "Klonen Sie jetzt Ihre Stimme", 181 tr: "Åimdi sesini klonla", 182 sv: "Klona din röst nu", 183 el: "ÎλÏνοÏοιήÏÏε Ïη ÏÏνή ÏÎ±Ï ÏÏÏα", 184 it: "Clona la tua voce ora", 185 ru: "ÐлониÑÑйÑе Ñвой Ð³Ð¾Ð»Ð¾Ñ ÑейÑаÑ", 186 zh: "ç°å¨å éä½ ç声é³", 187 ja: "ä»ããããªãã®å£°ãã¯ãã¼ã³", 188 hi: "ठब ठपनॠà¤à¤µà¤¾à¤à¤¼ à¤à¥à¤²à¥à¤¨ à¤à¤°à¥à¤" 189 } 190}; 191 192function getTranslation(key, langCode) { 193 const targetLang = getMappedLang(langCode); 194 let shortCode = "en"; 195 if (targetLang.startsWith("ar")) shortCode = "ar"; 196 else if (targetLang.startsWith("es")) shortCode = "es"; 197 else if (targetLang.startsWith("fr")) shortCode = "fr"; 198 else if (targetLang.startsWith("pt")) shortCode = "pt"; 199 else if (targetLang.startsWith("de")) shortCode = "de"; 200 else if (targetLang.startsWith("tr")) shortCode = "tr"; 201 else if (targetLang.startsWith("sv")) shortCode = "sv"; 202 else if (targetLang.startsWith("el")) shortCode = "el"; 203 else if (targetLang.startsWith("it")) shortCode = "it"; 204 else if (targetLang.startsWith("ru")) shortCode = "ru"; 205 else if (targetLang.startsWith("zh")) shortCode = "zh"; 206 else if (targetLang.startsWith("ja")) shortCode = "ja"; 207 else if (targetLang.startsWith("hi")) shortCode = "hi"; 208 209 return TRANSLATIONS[key][shortCode] || TRANSLATIONS[key]['en']; 210} 211 212// Helper functions for frontend 213function getMappedLang(langCode) { 214 if (!langCode) return "en"; 215 const lower = langCode.toLowerCase(); 216 217 // Arabic 218 if (lower === "ar" || lower === "ar-ae") return "ar-AE"; 219 220 // English 221 if (lower === "en" || lower === "en-us") return "en"; 222 if (lower === "en-gb") return "en-GB"; 223 if (lower === "en-ng") return "en-NG"; 224 225 // European 226 if (lower === "fr" || lower === "fr-fr") return "fr-FR"; 227 if (lower === "es" || lower === "es-es") return "es-ES"; 228 if (lower === "pt" || lower === "pt-br") return "pt-BR"; 229 if (lower === "de" || lower === "de-de") return "de-DE"; 230 if (lower === "tr" || lower === "tr-tr") return "tr-TR"; 231 if (lower === "sv" || lower === "sv-se") return "sv-SE"; 232 if (lower === "el" || lower === "el-gr") return "el-GR"; 233 if (lower === "it" || lower === "it-it") return "it-IT"; 234 235 // Asian + Russian 236 if (lower === "ru" || lower === "ru-ru") return "ru-RU"; 237 if (lower === "zh" || lower === "zh-cn") return "zh-CN"; 238 if (lower === "ja" || lower === "ja-jp") return "ja-JP"; 239 if (lower === "hi" || lower === "hi-in") return "hi-IN"; 240 241 return "en"; 242} 243 244function getVoicesByLang(langCode) { 245 const targetLang = getMappedLang(langCode); 246 return VOICES.filter(v => v.voiceLang === targetLang); 247} 248 249function getEmotionLabel(emotionId, langCode) { 250 const emotion = EMOTIONS.find(e => e.id === emotionId); 251 if (!emotion) return emotionId; 252 253 // Map full lang code (e.g. "ar-AE") to short code used in labels (e.g. "ar") 254 const targetLang = getMappedLang(langCode); 255 let shortCode = "en"; // default 256 257 if (targetLang.startsWith("ar")) shortCode = "ar"; 258 else if (targetLang.startsWith("es")) shortCode = "es"; 259 else if (targetLang.startsWith("fr")) shortCode = "fr"; 260 else if (targetLang.startsWith("pt")) shortCode = "pt"; 261 else if (targetLang.startsWith("de")) shortCode = "de"; 262 else if (targetLang.startsWith("tr")) shortCode = "tr"; 263 else if (targetLang.startsWith("sv")) shortCode = "sv"; 264 else if (targetLang.startsWith("el")) shortCode = "el"; 265 else if (targetLang.startsWith("it")) shortCode = "it"; 266 else if (targetLang.startsWith("ru")) shortCode = "ru"; 267 else if (targetLang.startsWith("zh")) shortCode = "zh"; 268 else if (targetLang.startsWith("ja")) shortCode = "ja"; 269 else if (targetLang.startsWith("hi")) shortCode = "hi"; 270 271 return emotion.labels[shortCode] || emotion.labels['en']; 272}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.