|
|
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 = { |
|
|
|
|
|
'ch': 'Χ', 'ts': 'Χ¦', 'tz': 'Χ¦', 'sh': 'Χ©', 'kh': 'Χ', |
|
|
|
|
|
|
|
|
'a': 'Χ', 'b': 'Χ', 'g': 'Χ', 'd': 'Χ', 'h': 'Χ', 'v': 'Χ', 'w': 'Χ', |
|
|
'z': 'Χ', 't': 'Χ', 'y': 'Χ', 'k': 'Χ', 'l': 'Χ', 'm': 'Χ', |
|
|
'n': 'Χ ', 's': 'Χ‘', 'p': 'Χ€', 'f': 'Χ€', 'q': 'Χ§', 'r': 'Χ¨', |
|
|
|
|
|
|
|
|
'e': 'ΦΆ', 'i': 'Φ΄', 'o': 'ΦΉ', 'u': 'Φ»', |
|
|
|
|
|
|
|
|
' ': ' ', '.': '.', ',': ',', '?': '?', '!': '!' |
|
|
} |
|
|
|
|
|
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): |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
full_translation = GoogleTranslator(source='iw', target='en').translate(hebrew_text) |
|
|
|
|
|
|
|
|
words = hebrew_text.strip().split() |
|
|
|
|
|
if len(words) > 1: |
|
|
individual_translations = [] |
|
|
for i, word in enumerate(words[:5], 1): |
|
|
if len(word.strip()) > 1: |
|
|
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: |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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.") |
|
|
|
|
|
|
|
|
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** β ΧΧΧΧ ΧΧ‘ |
|
|
""") |
|
|
|
|
|
|
|
|
with gr.Accordion("π Interactive Hebrew Alphabet Guide with Audio", open=False): |
|
|
gr.Markdown("### Click the speaker buttons to hear each letter's pronunciation:") |
|
|
|
|
|
|
|
|
letter_audio = gr.Audio(label="Letter Pronunciation", autoplay=True) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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 = gr.Radio( |
|
|
choices=["Translation", "Transliteration"], |
|
|
value="Transliteration", |
|
|
label="Conversion Mode" |
|
|
) |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
hebrew_audio = gr.Audio(label="Hebrew Audio", type="filepath") |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
def process_convert(text, mode): |
|
|
if mode == "Transliteration": |
|
|
return transliterate(text) |
|
|
else: |
|
|
return google_translate_hebrew(text) |
|
|
|
|
|
|
|
|
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() |