HeEn / app.py
kambris's picture
Update app.py
10d2fcb verified
import gradio as gr
from gtts import gTTS
import tempfile
from deep_translator import GoogleTranslator
import gradio as gr
from gtts import gTTS
import tempfile
from deep_translator import GoogleTranslator
transliteration_map = {
# Two-character combinations (check first)
'ch': 'Χ—', 'ts': 'Χ¦', 'tz': 'Χ¦', 'sh': 'Χ©', 'kh': 'Χ›',
# Single characters
'a': 'א', 'b': 'Χ‘', 'g': 'Χ’', 'd': 'Χ“', 'h': 'Χ”', 'v': 'Χ•', 'w': 'Χ•',
'z': 'Χ–', 't': 'ט', 'y': 'Χ™', 'k': 'Χ›', 'l': 'ל', 'm': 'מ',
'n': 'Χ ', 's': 'Χ‘', 'p': 'Χ€', 'f': 'Χ€', 'q': 'Χ§', 'r': 'Χ¨',
# Vowels
'e': 'ΦΆ', 'i': 'Φ΄', 'o': 'ΦΉ', 'u': 'Φ»',
# Space and punctuation
' ': ' ', '.': '.', ',': ',', '?': '?', '!': '!'
}
def generate_letter_audio(hebrew_letter):
"""Generate TTS audio for a single Hebrew letter or character."""
if not hebrew_letter or not hebrew_letter.strip():
return None
try:
tts = gTTS(text=hebrew_letter, lang='iw', slow=True)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
temp_path = tmp_file.name
tts.save(temp_path)
return temp_path
except Exception as e:
print(f"Letter TTS Error: {e}")
return None
def transliterate(text):
"""Convert English text to Hebrew transliteration"""
if not text:
return ""
text = text.lower()
result = []
i = 0
while i < len(text):
# Check for two-letter combinations first
if i < len(text) - 1:
two_char = text[i:i+2]
if two_char in transliteration_map:
result.append(transliteration_map[two_char])
i += 2
continue
# Check for single letter
char = text[i]
if char in transliteration_map:
result.append(transliteration_map[char])
elif char == ' ':
result.append(' ')
else:
result.append(char)
i += 1
return ''.join(result)
def google_translate_hebrew(english_text):
"""Translate English text to Hebrew using Google Translate"""
if not english_text or not english_text.strip():
return "No text provided for translation."
try:
translation_text = GoogleTranslator(source='en', target='iw').translate(english_text)
return translation_text
except Exception as e:
return f"❌ Google Translate error: {str(e)}\n\nPlease check your internet connection and try again."
def translate_multiple_words(hebrew_text):
"""Translate multiple Hebrew words - both individually and as a whole phrase"""
if not hebrew_text or not hebrew_text.strip():
return "No text provided for translation."
try:
# First translate the whole phrase
full_translation = GoogleTranslator(source='iw', target='en').translate(hebrew_text)
# Then translate individual words if there are multiple words
words = hebrew_text.strip().split()
if len(words) > 1:
individual_translations = []
for i, word in enumerate(words[:5], 1): # Limit to first 5 words
if len(word.strip()) > 1: # Skip single characters
try:
word_translation = GoogleTranslator(source='iw', target='en').translate(word)
individual_translations.append(f"**{i}. {word}** β†’ {word_translation}")
except:
individual_translations.append(f"**{i}. {word}** β†’ (translation failed)")
if individual_translations:
result = full_translation + "\n\n" + "─"*50 + "\n\n"
result += "πŸ“ **Individual Word Translations:**\n\n"
result += "\n".join(individual_translations)
return result
return full_translation
except Exception as e:
return f"❌ Translation error: {str(e)}"
def reverse_translate_english(hebrew_text):
"""Translate Hebrew text to English using Google Translate"""
if not hebrew_text or not hebrew_text.strip():
return "No text provided for translation."
try:
# Translate to English
translation_text = GoogleTranslator(source='iw', target='en').translate(hebrew_text)
return translation_text
except Exception as e:
return f"❌ Translation error: {str(e)}"
def hebrew_tts(hebrew_text):
"""Generate TTS audio for Hebrew text."""
if not hebrew_text or not hebrew_text.strip():
return None
try:
tts = gTTS(text=hebrew_text, lang='iw', slow=False)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
temp_path = tmp_file.name
tts.save(temp_path)
return temp_path
except Exception as e:
print(f"Hebrew TTS Error: {e}")
return None
def transliterate_and_speak(english_text):
"""Combined function to transliterate and generate audio."""
hebrew_text = transliterate(english_text)
hebrew_audio = hebrew_tts(hebrew_text)
return hebrew_text, hebrew_audio
def full_process_with_translation(english_text, mode):
"""Complete processing: translate/transliterate, generate audio, and get word translations"""
if mode == "Transliteration":
hebrew_text = transliterate(english_text)
else:
hebrew_text = google_translate_hebrew(english_text)
hebrew_audio = hebrew_tts(hebrew_text)
translation_result = translate_multiple_words(hebrew_text)
return hebrew_text, hebrew_audio, translation_result
# Create Gradio interface with custom CSS for copy buttons
css = """
.copy-btn {
font-size: 12px !important;
padding: 4px 8px !important;
min-width: 60px !important;
}
"""
with gr.Blocks(title="English to Hebrew Converter", css=css) as demo:
gr.Markdown("## πŸ“ English-to-Hebrew Converter")
gr.Markdown("Enter English text to convert to Hebrew script, generate audio, and get translations using Google Translate.")
# English to Hebrew Letter Mapping Guide
with gr.Accordion("πŸ”€ English ↔ Hebrew Letter Mapping Guide", open=False):
gr.Markdown("""
### How English Letters Map to Hebrew
This shows the transliteration mapping used in **Transliteration** mode:
""")
with gr.Row():
with gr.Column():
gr.Markdown("""
#### Consonants:
- **a** β†’ א (alef)
- **b** β†’ Χ‘ (bet)
- **g** β†’ Χ’ (gimel)
- **d** β†’ Χ“ (dalet)
- **h** β†’ Χ” (he)
- **v, w** β†’ Χ• (vav)
- **z** β†’ Χ– (zayin)
- **t** β†’ ט (tet)
- **y** β†’ Χ™ (yod)
- **k** β†’ Χ› (kaf)
- **l** β†’ ל (lamed)
- **m** β†’ מ (mem)
""")
with gr.Column():
gr.Markdown("""
#### More Consonants:
- **n** β†’ Χ  (nun)
- **s** β†’ Χ‘ (samekh)
- **p, f** β†’ Χ€ (pe/fe)
- **q** β†’ Χ§ (qof)
- **r** β†’ Χ¨ (resh)
#### Special Combinations:
- **ch** β†’ Χ— (chet)
- **kh** β†’ Χ› (kaf)
- **sh** β†’ Χ© (shin)
- **ts, tz** β†’ Χ¦ (tsadi)
""")
with gr.Column():
gr.Markdown("""
#### Vowel Marks:
- **e** β†’ ΦΆ (segol)
- **i** β†’ Φ΄ (hiriq)
- **o** β†’ ΦΉ (holam)
- **u** β†’ Φ» (kubutz)
#### Examples:
- **shalom** β†’ שאלֹמ
- **hello** β†’ Χ”ΦΆΧœΧœΦΉ
- **thanks** β†’ Χ˜Χ”ΧΧ Χ›Χ‘
""")
# Full-width transliteration guide with audio buttons
with gr.Accordion("πŸ“– Interactive Hebrew Alphabet Guide with Audio", open=False):
gr.Markdown("### Click the speaker buttons to hear each letter's pronunciation:")
# Audio component for letter playback
letter_audio = gr.Audio(label="Letter Pronunciation", autoplay=True)
# Consonants (Row 1)
gr.Markdown("#### Consonants:")
with gr.Row():
gr.Button("πŸ”Š א alef (a)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("א"), outputs=letter_audio)
gr.Button("πŸ”Š Χ‘ bet (b)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ‘"), outputs=letter_audio)
gr.Button("πŸ”Š Χ’ gimel (g)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ’"), outputs=letter_audio)
gr.Button("πŸ”Š Χ“ dalet (d)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ“"), outputs=letter_audio)
gr.Button("πŸ”Š Χ” he (h)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ”"), outputs=letter_audio)
# Consonants (Row 2)
with gr.Row():
gr.Button("πŸ”Š Χ• vav (v/w)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ•"), outputs=letter_audio)
gr.Button("πŸ”Š Χ– zayin (z)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ–"), outputs=letter_audio)
gr.Button("πŸ”Š Χ— chet (ch)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ—"), outputs=letter_audio)
gr.Button("πŸ”Š ט tet (t)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("ט"), outputs=letter_audio)
gr.Button("πŸ”Š Χ™ yod (y)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ™"), outputs=letter_audio)
# Consonants (Row 3)
with gr.Row():
gr.Button("πŸ”Š Χ› kaf (k/kh)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ›"), outputs=letter_audio)
gr.Button("πŸ”Š ל lamed (l)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("ל"), outputs=letter_audio)
gr.Button("πŸ”Š מ mem (m)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("מ"), outputs=letter_audio)
gr.Button("πŸ”Š Χ  nun (n)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ "), outputs=letter_audio)
gr.Button("πŸ”Š Χ‘ samekh (s)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ‘"), outputs=letter_audio)
# Consonants (Row 4)
with gr.Row():
gr.Button("πŸ”Š Χ’ ayin", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ’"), outputs=letter_audio)
gr.Button("πŸ”Š Χ€ pe (p/f)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ€"), outputs=letter_audio)
gr.Button("πŸ”Š Χ¦ tsadi (ts/tz)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ¦"), outputs=letter_audio)
gr.Button("πŸ”Š Χ§ qof (q)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ§"), outputs=letter_audio)
gr.Button("πŸ”Š Χ¨ resh (r)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ¨"), outputs=letter_audio)
# Consonants (Row 5)
with gr.Row():
gr.Button("πŸ”Š Χ© shin (sh)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χ©"), outputs=letter_audio)
gr.Button("πŸ”Š Χͺ tav (t)", size="sm").click(fn=generate_letter_audio, inputs=gr.State("Χͺ"), outputs=letter_audio)
# Mode selection
mode = gr.Radio(
choices=["Translation", "Transliteration"],
value="Transliteration",
label="Conversion Mode"
)
# Main interface with copy buttons
with gr.Row():
with gr.Column():
with gr.Row():
english_input = gr.Textbox(
label="Enter English Text",
lines=3,
placeholder="Example: Hello, how are you?",
scale=5
)
copy_english_btn = gr.Button("πŸ“‹ Copy", size="sm", scale=1, elem_classes="copy-btn")
with gr.Column():
with gr.Row():
hebrew_output = gr.Textbox(
label="Hebrew Script",
lines=3,
rtl=True,
scale=5
)
copy_hebrew_btn = gr.Button("πŸ“‹ Copy", size="sm", scale=1, elem_classes="copy-btn")
# Translation output with copy button
with gr.Row():
translation_output = gr.Textbox(
label="Word-by-Word Translation Results",
lines=3,
placeholder="Translations will appear here...",
scale=5
)
copy_translation_btn = gr.Button("πŸ“‹ Copy", size="sm", scale=1, elem_classes="copy-btn")
# Button controls
with gr.Row():
convert_btn = gr.Button("πŸ”„ Convert", variant="primary")
tts_btn = gr.Button("πŸ”Š Generate Hebrew Sound", variant="secondary")
translate_btn = gr.Button("🌐 Google Translate", variant="secondary")
with gr.Row():
combined_btn = gr.Button("πŸ”„πŸ”Š Convert & Speak", variant="secondary")
complete_btn = gr.Button("πŸ”„πŸŒπŸ”Š Complete Process (Audio + Translation)", variant="primary")
# Audio output
with gr.Row():
hebrew_audio = gr.Audio(label="Hebrew Audio", type="filepath")
# Manual translation section
with gr.Accordion("πŸ” Manual Hebrew to English Translation", open=False):
with gr.Row():
with gr.Column():
with gr.Row():
manual_hebrew_input = gr.Textbox(
label="Enter Hebrew text to translate",
placeholder="Χ”Χ›Χ Χ‘ טקבט Χ‘Χ’Χ‘Χ¨Χ™Χͺ",
rtl=True,
lines=3,
scale=5
)
copy_manual_hebrew_btn = gr.Button("πŸ“‹ Copy", size="sm", scale=1, elem_classes="copy-btn")
manual_translate_btn = gr.Button("🌐 Translate to English", variant="secondary")
with gr.Column():
with gr.Row():
manual_translation_output = gr.Textbox(
label="English Translation",
lines=3,
scale=5
)
copy_manual_translation_btn = gr.Button("πŸ“‹ Copy", size="sm", scale=1, elem_classes="copy-btn")
# Event handlers
def process_convert(text, mode):
if mode == "Transliteration":
return transliterate(text)
else:
return google_translate_hebrew(text)
# Copy button functions
copy_english_btn.click(fn=lambda x: x, inputs=english_input, outputs=english_input, js="(x) => {navigator.clipboard.writeText(x); return x;}")
copy_hebrew_btn.click(fn=lambda x: x, inputs=hebrew_output, outputs=hebrew_output, js="(x) => {navigator.clipboard.writeText(x); return x;}")
copy_translation_btn.click(fn=lambda x: x, inputs=translation_output, outputs=translation_output, js="(x) => {navigator.clipboard.writeText(x); return x;}")
copy_manual_hebrew_btn.click(fn=lambda x: x, inputs=manual_hebrew_input, outputs=manual_hebrew_input, js="(x) => {navigator.clipboard.writeText(x); return x;}")
copy_manual_translation_btn.click(fn=lambda x: x, inputs=manual_translation_output, outputs=manual_translation_output, js="(x) => {navigator.clipboard.writeText(x); return x;}")
convert_btn.click(
fn=process_convert,
inputs=[english_input, mode],
outputs=hebrew_output
)
tts_btn.click(
fn=hebrew_tts,
inputs=hebrew_output,
outputs=hebrew_audio
)
translate_btn.click(
fn=translate_multiple_words,
inputs=hebrew_output,
outputs=translation_output
)
combined_btn.click(
fn=lambda text, mode: transliterate_and_speak(text) if mode == "Transliteration" else (google_translate_hebrew(text), hebrew_tts(google_translate_hebrew(text))),
inputs=[english_input, mode],
outputs=[hebrew_output, hebrew_audio]
)
complete_btn.click(
fn=full_process_with_translation,
inputs=[english_input, mode],
outputs=[hebrew_output, hebrew_audio, translation_output]
)
manual_translate_btn.click(
fn=reverse_translate_english,
inputs=manual_hebrew_input,
outputs=manual_translation_output
)
if __name__ == "__main__":
demo.launch()