kambris commited on
Commit
587675f
·
verified ·
1 Parent(s): add4beb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +291 -52
app.py CHANGED
@@ -1,13 +1,23 @@
1
  import gradio as gr
2
  import requests
 
 
3
 
4
- # Simple transliteration mapping (English phonetics to Hebrew letters)
5
  transliteration_map = {
 
 
 
 
6
  'a': 'א', 'b': 'ב', 'g': 'ג', 'd': 'ד', 'h': 'ה', 'v': 'ו', 'w': 'ו',
7
- 'z': 'ז', 'ch': 'ח', 't': 'ט', 'y': 'י', 'k': 'כ', 'l': 'ל', 'm': 'מ',
8
- 'n': 'נ', 's': 'ס', 'p': 'פ', 'f': 'פ', 'ts': 'צ', 'q': 'ק', 'r': 'ר',
9
- 'sh': 'ש', 'th': 'ת',
10
- 'e': 'ֶ', 'i': 'ִ', 'o': 'ֹ', 'u': 'ֻ'
 
 
 
 
11
  }
12
 
13
  def transliterate(text):
@@ -35,7 +45,7 @@ def transliterate(text):
35
  elif char == ' ':
36
  result.append(' ')
37
  else:
38
- result.append(char) # Keep unknown characters as-is
39
 
40
  i += 1
41
 
@@ -43,11 +53,10 @@ def transliterate(text):
43
 
44
  def translate_text(text):
45
  """Translate English text to Hebrew using LibreTranslate API"""
46
- if not text:
47
  return ""
48
 
49
  try:
50
- # Using LibreTranslate public API
51
  url = "https://libretranslate.com/translate"
52
  payload = {
53
  "q": text,
@@ -56,42 +65,219 @@ def translate_text(text):
56
  "format": "text"
57
  }
58
 
59
- headers = {
60
- "Content-Type": "application/json"
61
- }
62
-
63
  response = requests.post(url, json=payload, headers=headers, timeout=10)
64
 
65
  if response.status_code == 200:
66
  result = response.json()
67
  return result.get('translatedText', 'Translation failed')
68
  else:
69
- return f"Error {response.status_code}: Unable to translate. Please try again."
70
 
71
  except requests.exceptions.Timeout:
72
- return "Translation timed out. Please check your internet connection and try again."
73
- except requests.exceptions.RequestException as e:
74
- return f"Network error: Unable to reach translation service."
75
  except Exception as e:
76
- return f"Unexpected error: {str(e)}"
77
 
78
- def process_text(text, mode):
79
- """Process text based on selected mode"""
80
- if not text:
81
- return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  if mode == "Transliteration (phonetic)":
84
- return transliterate(text)
85
- else: # Translation (meaning)
86
- return translate_text(text)
 
 
 
 
 
87
 
88
  # Create the Gradio interface
89
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
90
  gr.Markdown("# 🔤 English to Hebrew Converter")
91
- gr.Markdown("Convert English to Hebrew using transliteration or translation")
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  mode = gr.Radio(
94
- choices=["Transliteration (phonetic)", "Translation (meaning)"],
95
  value="Translation (meaning)",
96
  label="Conversion Mode"
97
  )
@@ -102,9 +288,15 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
102
  label="Type in English",
103
  placeholder="Hello, thank you, good morning...",
104
  lines=5,
105
- autofocus=True
 
106
  )
107
- convert_btn = gr.Button("Convert", variant="primary", size="lg")
 
 
 
 
 
108
  clear_btn = gr.Button("Clear", variant="secondary")
109
 
110
  with gr.Column():
@@ -114,53 +306,100 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
114
  rtl=True,
115
  show_copy_button=True
116
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
- # Button click event
119
  convert_btn.click(
120
  fn=process_text,
121
  inputs=[english_input, mode],
122
  outputs=hebrew_output
123
  )
124
 
125
- # Clear button
 
 
 
 
 
 
 
 
 
 
 
126
  clear_btn.click(
127
- fn=lambda: ("", ""),
128
  inputs=None,
129
- outputs=[english_input, hebrew_output]
 
 
 
 
 
 
130
  )
131
 
132
- # Also update on Enter key
133
  english_input.submit(
134
  fn=process_text,
135
  inputs=[english_input, mode],
136
  outputs=hebrew_output
137
  )
138
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  gr.Markdown("""
140
  ### How to use:
141
 
 
 
 
 
142
  **Transliteration mode** (phonetic):
143
  - Converts English letters to Hebrew letters by sound
144
  - Example: "shalom" → "שלום"
145
- - Good for Hebrew words written in English
146
-
147
- **Translation mode** (meaning):
148
- - Translates English words/sentences to Hebrew meaning
149
- - Example: "hello" → "שלום", "thank you" → "תודה"
150
- - Uses LibreTranslate API for accurate translation
151
  """)
152
-
153
- with gr.Row():
154
- gr.Examples(
155
- examples=[
156
- ["Hello", "Translation (meaning)"],
157
- ["Thank you", "Translation (meaning)"],
158
- ["Good morning", "Translation (meaning)"],
159
- ["shalom", "Transliteration (phonetic)"],
160
- ["todah rabah", "Transliteration (phonetic)"],
161
- ],
162
- inputs=[english_input, mode],
163
- )
164
 
165
  if __name__ == "__main__":
166
  demo.launch()
 
1
  import gradio as gr
2
  import requests
3
+ from gtts import gTTS
4
+ import tempfile
5
 
6
+ # Enhanced transliteration mapping (English phonetics to Hebrew letters)
7
  transliteration_map = {
8
+ # Two-character combinations (check first)
9
+ 'ch': 'ח', 'ts': 'צ', 'tz': 'צ', 'sh': 'ש', 'kh': 'כ',
10
+
11
+ # Single characters
12
  'a': 'א', 'b': 'ב', 'g': 'ג', 'd': 'ד', 'h': 'ה', 'v': 'ו', 'w': 'ו',
13
+ 'z': 'ז', 't': 'ט', 'y': 'י', 'k': 'כ', 'l': 'ל', 'm': 'מ',
14
+ 'n': 'נ', 's': 'ס', 'p': 'פ', 'f': 'פ', 'q': 'ק', 'r': 'ר',
15
+
16
+ # Vowels
17
+ 'e': 'ֶ', 'i': 'ִ', 'o': 'ֹ', 'u': 'ֻ',
18
+
19
+ # Space and punctuation
20
+ ' ': ' ', '.': '.', ',': ',', '?': '?', '!': '!'
21
  }
22
 
23
  def transliterate(text):
 
45
  elif char == ' ':
46
  result.append(' ')
47
  else:
48
+ result.append(char)
49
 
50
  i += 1
51
 
 
53
 
54
  def translate_text(text):
55
  """Translate English text to Hebrew using LibreTranslate API"""
56
+ if not text or not text.strip():
57
  return ""
58
 
59
  try:
 
60
  url = "https://libretranslate.com/translate"
61
  payload = {
62
  "q": text,
 
65
  "format": "text"
66
  }
67
 
68
+ headers = {"Content-Type": "application/json"}
 
 
 
69
  response = requests.post(url, json=payload, headers=headers, timeout=10)
70
 
71
  if response.status_code == 200:
72
  result = response.json()
73
  return result.get('translatedText', 'Translation failed')
74
  else:
75
+ return f"Error {response.status_code}: Unable to translate"
76
 
77
  except requests.exceptions.Timeout:
78
+ return "Translation timed out. Check your connection."
79
+ except requests.exceptions.RequestException:
80
+ return "Network error: Unable to reach translation service."
81
  except Exception as e:
82
+ return f"Error: {str(e)}"
83
 
84
+ def translate_multiple_words(hebrew_text):
85
+ """Translate multiple Hebrew words - both individually and as a phrase"""
86
+ if not hebrew_text or not hebrew_text.strip():
87
+ return "No text provided for translation."
88
+
89
+ try:
90
+ # Translate the full phrase
91
+ url = "https://libretranslate.com/translate"
92
+ payload = {"q": hebrew_text, "source": "he", "target": "en", "format": "text"}
93
+ headers = {"Content-Type": "application/json"}
94
+
95
+ response = requests.post(url, json=payload, headers=headers, timeout=10)
96
+
97
+ if response.status_code == 200:
98
+ full_translation = response.json().get('translatedText', '')
99
+ else:
100
+ full_translation = "Translation failed"
101
+
102
+ # Translate individual words if multiple
103
+ words = hebrew_text.strip().split()
104
+
105
+ if len(words) > 1:
106
+ individual_translations = []
107
+ for i, word in enumerate(words[:5], 1):
108
+ if len(word.strip()) > 1:
109
+ try:
110
+ payload = {"q": word, "source": "he", "target": "en", "format": "text"}
111
+ response = requests.post(url, json=payload, headers=headers, timeout=5)
112
+ if response.status_code == 200:
113
+ word_trans = response.json().get('translatedText', '(failed)')
114
+ else:
115
+ word_trans = "(failed)"
116
+ individual_translations.append(f"**{i}. {word}** → {word_trans}")
117
+ except:
118
+ individual_translations.append(f"**{i}. {word}** → (failed)")
119
+
120
+ if individual_translations:
121
+ result = full_translation + "\n\n" + "─"*50 + "\n\n"
122
+ result += "📝 **Individual Word Translations:**\n\n"
123
+ result += "\n".join(individual_translations)
124
+ return result
125
+
126
+ return full_translation
127
+
128
+ except Exception as e:
129
+ return f"Translation error: {str(e)}"
130
+
131
+ def reverse_translate(hebrew_text):
132
+ """Translate Hebrew to English"""
133
+ if not hebrew_text or not hebrew_text.strip():
134
+ return "No text provided"
135
 
136
+ try:
137
+ url = "https://libretranslate.com/translate"
138
+ payload = {"q": hebrew_text, "source": "he", "target": "en", "format": "text"}
139
+ headers = {"Content-Type": "application/json"}
140
+
141
+ response = requests.post(url, json=payload, headers=headers, timeout=10)
142
+
143
+ if response.status_code == 200:
144
+ return response.json().get('translatedText', 'Translation failed')
145
+ else:
146
+ return f"Error {response.status_code}"
147
+ except Exception as e:
148
+ return f"Error: {str(e)}"
149
+
150
+ def generate_hebrew_audio(hebrew_text):
151
+ """Generate TTS audio for Hebrew text"""
152
+ if not hebrew_text or not hebrew_text.strip():
153
+ return None
154
+
155
+ try:
156
+ tts = gTTS(text=hebrew_text, lang='iw', slow=False) # 'iw' is Hebrew language code
157
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
158
+ temp_path = tmp_file.name
159
+ tts.save(temp_path)
160
+ return temp_path
161
+ except Exception as e:
162
+ print(f"TTS Error: {e}")
163
+ return None
164
+
165
+ def generate_letter_audio(hebrew_letter):
166
+ """Generate TTS audio for a single Hebrew letter"""
167
+ if not hebrew_letter or not hebrew_letter.strip():
168
+ return None
169
+
170
+ try:
171
+ tts = gTTS(text=hebrew_letter, lang='iw', slow=True)
172
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
173
+ temp_path = tmp_file.name
174
+ tts.save(temp_path)
175
+ return temp_path
176
+ except Exception as e:
177
+ print(f"Letter TTS Error: {e}")
178
+ return None
179
+
180
+ def full_process(text, mode):
181
+ """Complete process: transliterate/translate and generate audio"""
182
  if mode == "Transliteration (phonetic)":
183
+ hebrew_text = transliterate(text)
184
+ else:
185
+ hebrew_text = translate_text(text)
186
+
187
+ audio = generate_hebrew_audio(hebrew_text)
188
+ translation = translate_multiple_words(hebrew_text) if hebrew_text else ""
189
+
190
+ return hebrew_text, audio, translation
191
 
192
  # Create the Gradio interface
193
+ with gr.Blocks(theme=gr.themes.Soft(), title="English to Hebrew Converter") as demo:
194
  gr.Markdown("# 🔤 English to Hebrew Converter")
195
+ gr.Markdown("Convert English to Hebrew with transliteration, translation, and audio")
196
 
197
+ # Interactive letter guide with audio
198
+ with gr.Accordion("📖 Interactive Hebrew Alphabet Guide with Audio", open=False):
199
+ gr.Markdown("### Click to hear each letter's pronunciation:")
200
+
201
+ gr.Markdown("#### Consonants:")
202
+ with gr.Row():
203
+ gr.Button("🔊 א alef", size="sm").click(
204
+ fn=generate_letter_audio, inputs=gr.State("א"), outputs=gr.Audio(visible=False, autoplay=True)
205
+ )
206
+ gr.Button("🔊 ב bet", size="sm").click(
207
+ fn=generate_letter_audio, inputs=gr.State("ב"), outputs=gr.Audio(visible=False, autoplay=True)
208
+ )
209
+ gr.Button("🔊 ג gimel", size="sm").click(
210
+ fn=generate_letter_audio, inputs=gr.State("ג"), outputs=gr.Audio(visible=False, autoplay=True)
211
+ )
212
+ gr.Button("🔊 ד dalet", size="sm").click(
213
+ fn=generate_letter_audio, inputs=gr.State("ד"), outputs=gr.Audio(visible=False, autoplay=True)
214
+ )
215
+ gr.Button("🔊 ה he", size="sm").click(
216
+ fn=generate_letter_audio, inputs=gr.State("ה"), outputs=gr.Audio(visible=False, autoplay=True)
217
+ )
218
+
219
+ with gr.Row():
220
+ gr.Button("🔊 ו vav", size="sm").click(
221
+ fn=generate_letter_audio, inputs=gr.State("ו"), outputs=gr.Audio(visible=False, autoplay=True)
222
+ )
223
+ gr.Button("🔊 ז zayin", size="sm").click(
224
+ fn=generate_letter_audio, inputs=gr.State("ז"), outputs=gr.Audio(visible=False, autoplay=True)
225
+ )
226
+ gr.Button("🔊 ח chet", size="sm").click(
227
+ fn=generate_letter_audio, inputs=gr.State("ח"), outputs=gr.Audio(visible=False, autoplay=True)
228
+ )
229
+ gr.Button("🔊 ט tet", size="sm").click(
230
+ fn=generate_letter_audio, inputs=gr.State("ט"), outputs=gr.Audio(visible=False, autoplay=True)
231
+ )
232
+ gr.Button("🔊 י yod", size="sm").click(
233
+ fn=generate_letter_audio, inputs=gr.State("י"), outputs=gr.Audio(visible=False, autoplay=True)
234
+ )
235
+
236
+ with gr.Row():
237
+ gr.Button("🔊 כ kaf", size="sm").click(
238
+ fn=generate_letter_audio, inputs=gr.State("כ"), outputs=gr.Audio(visible=False, autoplay=True)
239
+ )
240
+ gr.Button("🔊 ל lamed", size="sm").click(
241
+ fn=generate_letter_audio, inputs=gr.State("ל"), outputs=gr.Audio(visible=False, autoplay=True)
242
+ )
243
+ gr.Button("🔊 מ mem", size="sm").click(
244
+ fn=generate_letter_audio, inputs=gr.State("מ"), outputs=gr.Audio(visible=False, autoplay=True)
245
+ )
246
+ gr.Button("🔊 נ nun", size="sm").click(
247
+ fn=generate_letter_audio, inputs=gr.State("נ"), outputs=gr.Audio(visible=False, autoplay=True)
248
+ )
249
+ gr.Button("🔊 ס samekh", size="sm").click(
250
+ fn=generate_letter_audio, inputs=gr.State("ס"), outputs=gr.Audio(visible=False, autoplay=True)
251
+ )
252
+
253
+ with gr.Row():
254
+ gr.Button("🔊 ע ayin", size="sm").click(
255
+ fn=generate_letter_audio, inputs=gr.State("ע"), outputs=gr.Audio(visible=False, autoplay=True)
256
+ )
257
+ gr.Button("🔊 פ pe", size="sm").click(
258
+ fn=generate_letter_audio, inputs=gr.State("פ"), outputs=gr.Audio(visible=False, autoplay=True)
259
+ )
260
+ gr.Button("🔊 צ tsadi", size="sm").click(
261
+ fn=generate_letter_audio, inputs=gr.State("צ"), outputs=gr.Audio(visible=False, autoplay=True)
262
+ )
263
+ gr.Button("🔊 ק qof", size="sm").click(
264
+ fn=generate_letter_audio, inputs=gr.State("ק"), outputs=gr.Audio(visible=False, autoplay=True)
265
+ )
266
+ gr.Button("🔊 ר resh", size="sm").click(
267
+ fn=generate_letter_audio, inputs=gr.State("ר"), outputs=gr.Audio(visible=False, autoplay=True)
268
+ )
269
+
270
+ with gr.Row():
271
+ gr.Button("🔊 ש shin", size="sm").click(
272
+ fn=generate_letter_audio, inputs=gr.State("ש"), outputs=gr.Audio(visible=False, autoplay=True)
273
+ )
274
+ gr.Button("🔊 ת tav", size="sm").click(
275
+ fn=generate_letter_audio, inputs=gr.State("ת"), outputs=gr.Audio(visible=False, autoplay=True)
276
+ )
277
+
278
+ # Main interface
279
  mode = gr.Radio(
280
+ choices=["Translation (meaning)", "Transliteration (phonetic)"],
281
  value="Translation (meaning)",
282
  label="Conversion Mode"
283
  )
 
288
  label="Type in English",
289
  placeholder="Hello, thank you, good morning...",
290
  lines=5,
291
+ autofocus=True,
292
+ show_copy_button=True
293
  )
294
+
295
+ with gr.Row():
296
+ convert_btn = gr.Button("🔄 Convert", variant="primary", size="lg")
297
+ speak_btn = gr.Button("🔊 Generate Audio", variant="secondary")
298
+ full_btn = gr.Button("🔄🔊 Convert & Speak", variant="primary")
299
+
300
  clear_btn = gr.Button("Clear", variant="secondary")
301
 
302
  with gr.Column():
 
306
  rtl=True,
307
  show_copy_button=True
308
  )
309
+
310
+ hebrew_audio = gr.Audio(label="Hebrew Audio", type="filepath")
311
+
312
+ # Translation output
313
+ translation_output = gr.Textbox(
314
+ label="Word-by-Word Translation",
315
+ lines=6,
316
+ show_copy_button=True
317
+ )
318
+
319
+ # Manual Hebrew to English translation
320
+ with gr.Accordion("🔍 Hebrew to English Translation", open=False):
321
+ with gr.Row():
322
+ with gr.Column():
323
+ hebrew_input = gr.Textbox(
324
+ label="Enter Hebrew text",
325
+ placeholder="הכנס טקסט בעברית",
326
+ rtl=True,
327
+ lines=3
328
+ )
329
+ translate_btn = gr.Button("🌐 Translate to English", variant="secondary")
330
+
331
+ with gr.Column():
332
+ english_output = gr.Textbox(
333
+ label="English Translation",
334
+ lines=3
335
+ )
336
+
337
+ # Event handlers
338
+ def process_text(text, mode):
339
+ if mode == "Transliteration (phonetic)":
340
+ return transliterate(text)
341
+ else:
342
+ return translate_text(text)
343
 
 
344
  convert_btn.click(
345
  fn=process_text,
346
  inputs=[english_input, mode],
347
  outputs=hebrew_output
348
  )
349
 
350
+ speak_btn.click(
351
+ fn=generate_hebrew_audio,
352
+ inputs=hebrew_output,
353
+ outputs=hebrew_audio
354
+ )
355
+
356
+ full_btn.click(
357
+ fn=full_process,
358
+ inputs=[english_input, mode],
359
+ outputs=[hebrew_output, hebrew_audio, translation_output]
360
+ )
361
+
362
  clear_btn.click(
363
+ fn=lambda: ("", "", None, ""),
364
  inputs=None,
365
+ outputs=[english_input, hebrew_output, hebrew_audio, translation_output]
366
+ )
367
+
368
+ translate_btn.click(
369
+ fn=reverse_translate,
370
+ inputs=hebrew_input,
371
+ outputs=english_output
372
  )
373
 
 
374
  english_input.submit(
375
  fn=process_text,
376
  inputs=[english_input, mode],
377
  outputs=hebrew_output
378
  )
379
 
380
+ # Examples
381
+ gr.Examples(
382
+ examples=[
383
+ ["Hello", "Translation (meaning)"],
384
+ ["Thank you", "Translation (meaning)"],
385
+ ["Good morning", "Translation (meaning)"],
386
+ ["shalom", "Transliteration (phonetic)"],
387
+ ["todah rabah", "Transliteration (phonetic)"],
388
+ ],
389
+ inputs=[english_input, mode],
390
+ )
391
+
392
  gr.Markdown("""
393
  ### How to use:
394
 
395
+ **Translation mode** (meaning):
396
+ - Translates English words/sentences to Hebrew
397
+ - Example: "hello" → "שלום", "thank you" → "תודה"
398
+
399
  **Transliteration mode** (phonetic):
400
  - Converts English letters to Hebrew letters by sound
401
  - Example: "shalom" → "שלום"
 
 
 
 
 
 
402
  """)
 
 
 
 
 
 
 
 
 
 
 
 
403
 
404
  if __name__ == "__main__":
405
  demo.launch()