# ============================================================================ # ENGLISH → URDU AI TRANSLATOR — app.py (Hugging Face Spaces ready) # Deploy: create a new Space (SDK: Gradio), upload this file + requirements.txt # ============================================================================ # ---------------------------------------------------------------------------- # 1. IMPORTS # ---------------------------------------------------------------------------- import re import torch import gradio as gr from transformers import MarianMTModel, MarianTokenizer # ---------------------------------------------------------------------------- # 2. LOAD THE FREE ENGLISH → URDU MODEL # ---------------------------------------------------------------------------- # Helsinki-NLP/opus-mt-en-ur is a free, open-source MarianMT model trained # specifically for English -> Urdu translation. It downloads automatically # from the Hugging Face Hub on first run and is cached afterwards. MODEL_NAME = "Helsinki-NLP/opus-mt-en-ur" print("Loading translation model...") device = "cuda" if torch.cuda.is_available() else "cpu" try: tokenizer = MarianTokenizer.from_pretrained(MODEL_NAME) model = MarianMTModel.from_pretrained(MODEL_NAME).to(device) model.eval() print(f"Model loaded successfully on device: {device}") except Exception as e: raise RuntimeError(f"Failed to load the translation model: {e}") # ---------------------------------------------------------------------------- # 3. TRANSLATION LOGIC # ---------------------------------------------------------------------------- def split_into_sentences(text: str): """ Split a paragraph into sentences so long, multi-sentence text is translated more accurately (MarianMT works best on shorter chunks). Keeps punctuation attached to each sentence. """ sentences = re.split(r'(?<=[.!?])\s+', text.strip()) return [s for s in sentences if s.strip()] def translate_en_to_ur(text: str) -> str: """ Translates English text (single sentence, multiple sentences, or a full paragraph) into Urdu using the loaded MarianMT model. Punctuation and paragraph breaks are preserved. """ if not text or not text.strip(): return "" # Preserve paragraph breaks by translating each paragraph separately paragraphs = text.split("\n") translated_paragraphs = [] for paragraph in paragraphs: if not paragraph.strip(): translated_paragraphs.append("") continue sentences = split_into_sentences(paragraph) translated_sentences = [] for sentence in sentences: inputs = tokenizer(sentence, return_tensors="pt", padding=True, truncation=True).to(device) with torch.no_grad(): translated_tokens = model.generate(**inputs, max_length=512, num_beams=4) translated_text = tokenizer.decode(translated_tokens[0], skip_special_tokens=True) translated_sentences.append(translated_text) translated_paragraphs.append(" ".join(translated_sentences)) return "\n".join(translated_paragraphs) def handle_translate(english_text: str, progress=gr.Progress()): """ Wrapper function called by the Gradio 'Translate' button. Handles empty input, shows progress, and catches errors gracefully. """ if not english_text or not english_text.strip(): return "⚠️ Please enter some English text to translate." try: progress(0.2, desc="Analyzing text...") progress(0.5, desc="Translating to Urdu...") result = translate_en_to_ur(english_text) progress(1.0, desc="Done!") if not result.strip(): return "⚠️ Could not generate a translation. Please try different text." return result except Exception as e: return f"❌ An error occurred during translation: {str(e)}" def count_characters(text: str) -> str: """Returns a live character/word count string for the input box.""" if not text: return "0 characters | 0 words" char_count = len(text) word_count = len(text.split()) return f"{char_count} characters | {word_count} words" def clear_fields(): """Resets the input box, output box, and character counter.""" return "", "", "0 characters | 0 words" # ---------------------------------------------------------------------------- # 4. CUSTOM CSS — MODERN, ROUNDED, SOFT-COLORED, RESPONSIVE UI # ---------------------------------------------------------------------------- custom_css = """ .gradio-container { font-family: 'Segoe UI', 'Poppins', sans-serif !important; background: linear-gradient(135deg, #f5f7fa 0%, #e8eef7 100%) !important; max-width: 900px !important; margin: auto !important; } #title_md h1 { text-align: center; font-weight: 700; background: linear-gradient(90deg, #2b6cb0, #38b2ac); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 0px; } #subtitle_md { text-align: center; color: #555; margin-top: 4px; margin-bottom: 20px; } .gr-box, .block { border-radius: 16px !important; box-shadow: 0 4px 12px rgba(0,0,0,0.06) !important; } textarea, input { border-radius: 14px !important; border: 1px solid #d6e0ea !important; } #translate_btn { background: linear-gradient(90deg, #2b6cb0, #38b2ac) !important; color: white !important; border-radius: 14px !important; font-weight: 600 !important; border: none !important; } #clear_btn { border-radius: 14px !important; font-weight: 600 !important; background: #f1f3f6 !important; color: #333 !important; border: 1px solid #ddd !important; } #char_counter { text-align: right; color: #888; font-size: 0.85em; } footer { visibility: hidden; } """ # ---------------------------------------------------------------------------- # 5. EXAMPLE SENTENCES # ---------------------------------------------------------------------------- example_sentences = [ "Hello, how are you today?", "I love reading books in my free time.", "The weather is beautiful this morning.", "Can you please help me with my homework?", "Pakistan is a country with a rich cultural heritage.", "Artificial intelligence is changing the world rapidly.", "Thank you very much for your kindness.", "Education is the key to a better future.", ] # ---------------------------------------------------------------------------- # 6. BUILD THE GRADIO BLOCKS INTERFACE # ---------------------------------------------------------------------------- with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="blue", secondary_hue="teal")) as demo: gr.Markdown("# 🌐 English → Urdu AI Translator", elem_id="title_md") gr.Markdown( "Translate English text into fluent Urdu instantly, powered by a free open-source " "Hugging Face model. Supports single sentences, multiple sentences, and full paragraphs.", elem_id="subtitle_md" ) with gr.Row(): with gr.Column(scale=1): english_input = gr.Textbox( label="✍️ English Text", placeholder="Type or paste English text here...", lines=8, ) char_counter = gr.Markdown("0 characters | 0 words", elem_id="char_counter") with gr.Row(): translate_btn = gr.Button("🔁 Translate", elem_id="translate_btn", variant="primary") clear_btn = gr.Button("🗑️ Clear", elem_id="clear_btn") with gr.Column(scale=1): urdu_output = gr.Textbox( label="🇵🇰 Urdu Translation", placeholder="اردو ترجمہ یہاں ظاہر ہوگا...", lines=8, rtl=True, interactive=False, ) gr.Markdown("### 💡 Try an example:") gr.Examples( examples=example_sentences, inputs=english_input, label="Example Sentences", ) # Event wiring english_input.change(fn=count_characters, inputs=english_input, outputs=char_counter) translate_btn.click(fn=handle_translate, inputs=english_input, outputs=urdu_output) english_input.submit(fn=handle_translate, inputs=english_input, outputs=urdu_output) clear_btn.click(fn=clear_fields, inputs=None, outputs=[english_input, urdu_output, char_counter]) # ---------------------------------------------------------------------------- # 7. LAUNCH — works both locally and on Hugging Face Spaces # ---------------------------------------------------------------------------- if __name__ == "__main__": demo.launch()