arindae commited on
Commit
245067e
1 Parent(s): 0c339bd

elevenlabs support fix

Browse files
translator_app/translator/__pycache__/views.cpython-314.pyc CHANGED
Binary files a/translator_app/translator/__pycache__/views.cpython-314.pyc and b/translator_app/translator/__pycache__/views.cpython-314.pyc differ
 
translator_app/translator/services/__pycache__/translation_service.cpython-314.pyc CHANGED
Binary files a/translator_app/translator/services/__pycache__/translation_service.cpython-314.pyc and b/translator_app/translator/services/__pycache__/translation_service.cpython-314.pyc differ
 
translator_app/translator/services/language_support.py CHANGED
@@ -49,10 +49,10 @@ MODEL_LANGUAGE_SUPPORT = {
49
  "madlad": {"en", "sw", "rw", "fr", "ar"},
50
  # DeepL has no coverage at all for sw/lg/nyn/ach/teo/lgg/rw.
51
  "deepl_fallback": {"en", "fr", "ar"},
52
- "google_fallback": None,
53
  }
54
 
55
- FALLBACK_MODEL = "google_fallback"
56
 
57
  # ElevenLabs eleven_multilingual_v2's real language list (per their docs as
58
  # of mid-2026). None of your East African languages are on it - only en/fr/ar
@@ -64,6 +64,21 @@ ELEVENLABS_MULTILINGUAL_V2_LANGUAGES = {
64
  "fi", "bg", "hr", "sk", "ta",
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  def supported_codes(model):
69
  """Set of codes a model supports, or None if unrestricted."""
 
49
  "madlad": {"en", "sw", "rw", "fr", "ar"},
50
  # DeepL has no coverage at all for sw/lg/nyn/ach/teo/lgg/rw.
51
  "deepl_fallback": {"en", "fr", "ar"},
52
+ "google": None,
53
  }
54
 
55
+ FALLBACK_MODEL = "google"
56
 
57
  # ElevenLabs eleven_multilingual_v2's real language list (per their docs as
58
  # of mid-2026). None of your East African languages are on it - only en/fr/ar
 
64
  "fi", "bg", "hr", "sk", "ta",
65
  }
66
 
67
+ ELEVENLABS_V3_LANGUAGES = {
68
+ "af", "sq", "am", "ar", "hy", "as", "az", "ba", "eu", "be",
69
+ "bn", "bos", "bg", "my", "ca", "ceb", "ny", "zh", "hr", "cs",
70
+ "da", "nl", "en", "eo", "et", "fil", "fi", "fr", "gl", "ka",
71
+ "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu",
72
+ "is", "ig", "id", "ga", "it", "ja", "jv", "kn", "kk", "km",
73
+ "rw", "ko", "ku", "ky", "lo", "la", "lv", "ln", "lt", "lb",
74
+ "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "ne", "no",
75
+ "or", "om", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm",
76
+ "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es",
77
+ "su", "sw", "sv", "tg", "ta", "tt", "te", "th", "tr", "tk",
78
+ "uk", "ur", "ug", "uz", "vi", "cy", "xh", "yi", "yo", "zu"
79
+ }
80
+
81
+
82
 
83
  def supported_codes(model):
84
  """Set of codes a model supports, or None if unrestricted."""
translator_app/translator/services/translation_service.py CHANGED
@@ -87,7 +87,7 @@ class TranslationService:
87
 
88
  if model == "deepl_fallback":
89
  outcome = self._translate_deepl(text, source_language, target_language)
90
- elif model == "google_fallback":
91
  # Explicit, user-selectable Google fallback. Reuses the exact
92
  # same free-fallback call already used internally elsewhere in
93
  # this class - no new translation logic introduced.
 
87
 
88
  if model == "deepl_fallback":
89
  outcome = self._translate_deepl(text, source_language, target_language)
90
+ elif model == "google":
91
  # Explicit, user-selectable Google fallback. Reuses the exact
92
  # same free-fallback call already used internally elsewhere in
93
  # this class - no new translation logic introduced.
translator_app/translator/templates/translator/translator.html CHANGED
@@ -85,13 +85,12 @@
85
  </button>
86
  <button id="copy-result" type="button"
87
  class="hidden rounded-full bg-mist px-3 py-1 text-xs font-bold text-primary hover:bg-stone-200 transition">
88
- 馃搵 Copy
89
  </button>
90
  </div>
91
  </div>
92
  <p id="translated-text" aria-live="polite"
93
- class="relative flex-1 whitespace-pre-wrap font-display text-2xl leading-relaxed text-primary">
94
- <span class="text-stone-300">Your translation will appear here.</span>
95
  </p>
96
  <p id="result-meta" class="mt-4 text-xs text-stone-400 border-t border-stone-100 pt-3"></p>
97
  </section>
@@ -220,7 +219,7 @@
220
  const srcOk = modelSelect.value === 'madlad' || !sourceSelect.value || allowed.has(sourceSelect.value);
221
  const tgtOk = !targetSelect.value || allowed.has(targetSelect.value);
222
  if (!srcOk || !tgtOk) {
223
- modelSelect.value = 'google_fallback';
224
  syncLanguagesForModel();
225
  message.textContent = 'Switched to Google Translate (fallback) - the previous model doesn\'t support this language.';
226
  }
 
85
  </button>
86
  <button id="copy-result" type="button"
87
  class="hidden rounded-full bg-mist px-3 py-1 text-xs font-bold text-primary hover:bg-stone-200 transition">
88
+ Copy
89
  </button>
90
  </div>
91
  </div>
92
  <p id="translated-text" aria-live="polite"
93
+ class="relative flex-1 whitespace-pre-wrap font-display text-2xl leading-relaxed text-primary"><span class="text-stone-300">Your translation will appear here.</span>
 
94
  </p>
95
  <p id="result-meta" class="mt-4 text-xs text-stone-400 border-t border-stone-100 pt-3"></p>
96
  </section>
 
219
  const srcOk = modelSelect.value === 'madlad' || !sourceSelect.value || allowed.has(sourceSelect.value);
220
  const tgtOk = !targetSelect.value || allowed.has(targetSelect.value);
221
  if (!srcOk || !tgtOk) {
222
+ modelSelect.value = 'google';
223
  syncLanguagesForModel();
224
  message.textContent = 'Switched to Google Translate (fallback) - the previous model doesn\'t support this language.';
225
  }
translator_app/translator/views.py CHANGED
@@ -38,7 +38,7 @@ def translator(request):
38
  'models': settings.TRANSLATION_MODELS,
39
  'default_model': settings.TRANSLATION_DEFAULT_MODEL,
40
  'model_language_support_json': model_language_support,
41
- 'elevenlabs_languages_json': sorted(language_support.ELEVENLABS_MULTILINGUAL_V2_LANGUAGES),
42
  })
43
 
44
 
@@ -118,6 +118,20 @@ def translate_api(request):
118
  return JsonResponse(result)
119
 
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  @require_POST
122
  def text_to_speech(request):
123
  if not settings.ELEVENLABS_API_KEY:
@@ -139,7 +153,7 @@ def text_to_speech(request):
139
 
140
  # Fail fast client-side instead of burning an API call: ElevenLabs'
141
  # multilingual model has no voice for these languages yet.
142
- if lang and lang not in language_support.ELEVENLABS_MULTILINGUAL_V2_LANGUAGES:
143
  return JsonResponse(
144
  {
145
  'error': 'ElevenLabs does not have a voice for this language yet.',
@@ -158,7 +172,7 @@ def text_to_speech(request):
158
  },
159
  json={
160
  'text': text,
161
- 'model_id': settings.ELEVENLABS_MODEL_ID,
162
  },
163
  timeout=20,
164
  )
 
38
  'models': settings.TRANSLATION_MODELS,
39
  'default_model': settings.TRANSLATION_DEFAULT_MODEL,
40
  'model_language_support_json': model_language_support,
41
+ 'elevenlabs_languages_json': sorted(language_support.ELEVENLABS_V3_LANGUAGES),
42
  })
43
 
44
 
 
118
  return JsonResponse(result)
119
 
120
 
121
+ def get_elevenlabs_model(lang_code: str) -> str:
122
+ """
123
+ Returns the cheapest compatible ElevenLabs model ID for a given language code.
124
+ Falls back to v3 if v2 does not support it.
125
+ """
126
+ clean_code = lang_code.lower().strip()
127
+
128
+ if clean_code in language_support.ELEVENLABS_MULTILINGUAL_V2_LANGUAGES:
129
+ return "eleven_multilingual_v2"
130
+ elif clean_code in language_support.ELEVENLABS_V3_LANGUAGES:
131
+ return "eleven_v3"
132
+ else:
133
+ raise ValueError(f"Language code '{lang_code}' is not supported by any ElevenLabs model.")
134
+
135
  @require_POST
136
  def text_to_speech(request):
137
  if not settings.ELEVENLABS_API_KEY:
 
153
 
154
  # Fail fast client-side instead of burning an API call: ElevenLabs'
155
  # multilingual model has no voice for these languages yet.
156
+ if lang and lang not in language_support.ELEVENLABS_V3_LANGUAGES:
157
  return JsonResponse(
158
  {
159
  'error': 'ElevenLabs does not have a voice for this language yet.',
 
172
  },
173
  json={
174
  'text': text,
175
+ 'model_id': get_elevenlabs_model(lang),
176
  },
177
  timeout=20,
178
  )
translator_app/translator_project/__pycache__/settings.cpython-314.pyc CHANGED
Binary files a/translator_app/translator_project/__pycache__/settings.cpython-314.pyc and b/translator_app/translator_project/__pycache__/settings.cpython-314.pyc differ
 
translator_app/translator_project/settings.py CHANGED
@@ -91,7 +91,6 @@ USE_TZ = True
91
 
92
  # Static files
93
  STATIC_URL = "static/"
94
- # STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
95
  STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
96
 
97
  # Media files
@@ -101,15 +100,14 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "media")
101
  # Default primary key field type
102
  DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
103
 
104
- # ML translation service. Point this at the deployed Hugging Face Space, e.g.
105
- # https://<account>-<space>.hf.space/api/translate
106
  MODEL_API_URL = os.getenv("MODEL_API_URL")
107
  TRANSLATION_DEFAULT_MODEL = os.getenv("TRANSLATION_DEFAULT_MODEL", "nllb")
108
  TRANSLATION_MODELS = (
109
  ("nllb", "NLLB-200 (600M 路 Fast)"),
110
  ("nllb_1_3b", "NLLB-200 (1.3B 路 Accurate)"),
111
  ("madlad", "MADLAD-400 (3B 路 Large)"),
112
- ("google_fallback", "Google Translate"),
113
  )
114
  TRANSLATION_MODEL_ENGINES = {
115
  "nllb": "nllb",
@@ -132,6 +130,5 @@ if TRANSLATION_API_KEY:
132
  # never send it to the browser. Get a key at https://elevenlabs.io/app/settings/api-keys
133
  # and a voice ID from https://elevenlabs.io/app/voice-library
134
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
135
- ELEVENLABS_VOICE_ID = os.getenv("ELEVENLABS_VOICE_ID", "21m00Tcm4TlvDq8ikWAM") # default: "Rachel"
136
- ELEVENLABS_MODEL_ID = os.getenv("ELEVENLABS_MODEL_ID", "eleven_multilingual_v2")
137
  ELEVENLABS_TTS_URL = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
 
91
 
92
  # Static files
93
  STATIC_URL = "static/"
 
94
  STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
95
 
96
  # Media files
 
100
  # Default primary key field type
101
  DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
102
 
103
+ # ML translation service
 
104
  MODEL_API_URL = os.getenv("MODEL_API_URL")
105
  TRANSLATION_DEFAULT_MODEL = os.getenv("TRANSLATION_DEFAULT_MODEL", "nllb")
106
  TRANSLATION_MODELS = (
107
  ("nllb", "NLLB-200 (600M 路 Fast)"),
108
  ("nllb_1_3b", "NLLB-200 (1.3B 路 Accurate)"),
109
  ("madlad", "MADLAD-400 (3B 路 Large)"),
110
+ ("google", "Google Translate"),
111
  )
112
  TRANSLATION_MODEL_ENGINES = {
113
  "nllb": "nllb",
 
130
  # never send it to the browser. Get a key at https://elevenlabs.io/app/settings/api-keys
131
  # and a voice ID from https://elevenlabs.io/app/voice-library
132
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
133
+ ELEVENLABS_VOICE_ID = os.getenv("ELEVENLABS_VOICE_ID", "hpp4J3VqNfWAUOO0d1Us")
 
134
  ELEVENLABS_TTS_URL = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"