Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| from deep_translator import GoogleTranslator | |
| import time | |
| # ================================ | |
| # PAGE CONFIGURATION | |
| # ================================ | |
| st.set_page_config( | |
| page_title="Urdu to Pashto Translator", | |
| page_icon="🌐", | |
| layout="wide", | |
| initial_sidebar_state="collapsed" | |
| ) | |
| # ================================ | |
| # CUSTOM CSS - GLASSMORPHISM THEME | |
| # ================================ | |
| def load_css(): | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Righteous&display=swap'); | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| /* Main Background */ | |
| .stApp { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #4facfe 75%, #00f2fe 100%); | |
| background-size: 400% 400%; | |
| animation: gradientShift 15s ease infinite; | |
| font-family: 'Poppins', sans-serif; | |
| } | |
| @keyframes gradientShift { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* Hide Streamlit Branding */ | |
| #MainMenu {visibility: hidden;} | |
| footer {visibility: hidden;} | |
| header {visibility: hidden;} | |
| /* Glass Container */ | |
| .glass-container { | |
| background: rgba(255, 255, 255, 0.15); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border-radius: 25px; | |
| border: 2px solid rgba(255, 255, 255, 0.3); | |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); | |
| padding: 40px; | |
| margin: 20px auto; | |
| max-width: 1200px; | |
| } | |
| /* Title Styling */ | |
| .main-title { | |
| font-family: 'Righteous', cursive; | |
| font-size: 3.5rem; | |
| text-align: center; | |
| background: linear-gradient(135deg, #ffffff 0%, #e0e7ff 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 10px; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.2); | |
| animation: titleGlow 3s ease-in-out infinite; | |
| } | |
| @keyframes titleGlow { | |
| 0%, 100% { filter: drop-shadow(0 0 10px rgba(255,255,255,0.5)); } | |
| 50% { filter: drop-shadow(0 0 20px rgba(255,255,255,0.8)); } | |
| } | |
| .subtitle { | |
| text-align: center; | |
| color: rgba(255, 255, 255, 0.9); | |
| font-size: 1.2rem; | |
| margin-bottom: 40px; | |
| font-weight: 300; | |
| } | |
| /* Text Areas */ | |
| .stTextArea textarea { | |
| background: rgba(255, 255, 255, 0.2) !important; | |
| backdrop-filter: blur(10px); | |
| border: 2px solid rgba(255, 255, 255, 0.4) !important; | |
| border-radius: 15px !important; | |
| color: #ffffff !important; | |
| font-size: 1.1rem !important; | |
| padding: 15px !important; | |
| font-family: 'Poppins', sans-serif !important; | |
| transition: all 0.3s ease; | |
| } | |
| .stTextArea textarea:focus { | |
| border-color: rgba(255, 255, 255, 0.8) !important; | |
| box-shadow: 0 0 20px rgba(255, 255, 255, 0.4) !important; | |
| transform: scale(1.02); | |
| } | |
| .stTextArea textarea::placeholder { | |
| color: rgba(255, 255, 255, 0.6) !important; | |
| } | |
| /* Labels */ | |
| .stTextArea label { | |
| color: #ffffff !important; | |
| font-weight: 600 !important; | |
| font-size: 1.1rem !important; | |
| margin-bottom: 10px !important; | |
| } | |
| /* 3D Button Styling */ | |
| .stButton button { | |
| background: linear-gradient(145deg, #667eea, #764ba2); | |
| color: white; | |
| border: none; | |
| border-radius: 15px; | |
| padding: 15px 40px; | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| font-family: 'Poppins', sans-serif; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4), | |
| inset 0 -3px 10px rgba(0, 0, 0, 0.2), | |
| inset 0 3px 10px rgba(255, 255, 255, 0.2); | |
| position: relative; | |
| overflow: hidden; | |
| width: 100%; | |
| } | |
| .stButton button:before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); | |
| transition: left 0.5s; | |
| } | |
| .stButton button:hover:before { | |
| left: 100%; | |
| } | |
| .stButton button:hover { | |
| transform: translateY(-3px) scale(1.05); | |
| box-shadow: 0 15px 35px rgba(102, 126, 234, 0.6), | |
| inset 0 -3px 10px rgba(0, 0, 0, 0.2), | |
| inset 0 3px 10px rgba(255, 255, 255, 0.3); | |
| } | |
| .stButton button:active { | |
| transform: translateY(0px) scale(1); | |
| box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); | |
| } | |
| /* Clear Button */ | |
| div[data-testid="column"]:last-child .stButton button { | |
| background: linear-gradient(145deg, #f093fb, #f5576c); | |
| box-shadow: 0 10px 25px rgba(245, 87, 108, 0.4); | |
| } | |
| div[data-testid="column"]:last-child .stButton button:hover { | |
| box-shadow: 0 15px 35px rgba(245, 87, 108, 0.6); | |
| } | |
| /* Info Box */ | |
| .info-box { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| border-radius: 15px; | |
| border: 1px solid rgba(255, 255, 255, 0.3); | |
| padding: 20px; | |
| margin: 20px 0; | |
| color: white; | |
| } | |
| .info-box h3 { | |
| color: #ffffff; | |
| font-weight: 600; | |
| margin-bottom: 10px; | |
| } | |
| .info-box p { | |
| color: rgba(255, 255, 255, 0.8); | |
| line-height: 1.6; | |
| } | |
| /* Loading Animation */ | |
| .stSpinner > div { | |
| border-top-color: #ffffff !important; | |
| } | |
| /* Success/Warning Messages */ | |
| .stSuccess, .stWarning, .stError { | |
| background: rgba(255, 255, 255, 0.2); | |
| backdrop-filter: blur(10px); | |
| border-radius: 10px; | |
| border: 1px solid rgba(255, 255, 255, 0.4); | |
| color: white !important; | |
| } | |
| /* Footer */ | |
| .footer { | |
| text-align: center; | |
| color: rgba(255, 255, 255, 0.7); | |
| margin-top: 50px; | |
| padding: 20px; | |
| font-size: 0.9rem; | |
| } | |
| /* Responsive Design */ | |
| @media (max-width: 768px) { | |
| .main-title { | |
| font-size: 2rem; | |
| } | |
| .subtitle { | |
| font-size: 1rem; | |
| } | |
| .glass-container { | |
| padding: 20px; | |
| } | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ================================ | |
| # TRANSLATION FUNCTIONS | |
| # ================================ | |
| def urdu_to_pashto_roman(urdu_text): | |
| """ | |
| Translate Urdu to Pashto and romanize it | |
| """ | |
| if not urdu_text.strip(): | |
| return "" | |
| try: | |
| # Step 1: Translate Urdu to Pashto using Google Translator | |
| translator_to_pashto = GoogleTranslator(source='ur', target='ps') | |
| pashto_text = translator_to_pashto.translate(urdu_text) | |
| # Step 2: Create Roman representation | |
| romanized = create_roman_representation(pashto_text) | |
| return romanized | |
| except Exception as e: | |
| return f"Translation error: {str(e)}" | |
| def create_roman_representation(pashto_text): | |
| """ | |
| Create a Roman Urdu representation of Pashto text | |
| """ | |
| # Comprehensive Pashto to Roman Urdu character mapping (phonetic) | |
| pashto_to_roman = { | |
| # Vowels | |
| 'ا': 'a', 'آ': 'aa', 'ع': 'a', 'ء': '', | |
| # Consonants | |
| 'ب': 'b', 'پ': 'p', 'ت': 't', 'ټ': 't', 'ث': 's', | |
| 'ج': 'j', 'چ': 'ch', 'ح': 'h', 'خ': 'kh', | |
| 'د': 'd', 'ډ': 'd', 'ذ': 'z', 'ر': 'r', 'ړ': 'r', | |
| 'ز': 'z', 'ژ': 'zh', 'ږ': 'g', 'س': 's', 'ش': 'sh', | |
| 'ښ': 'x', 'ص': 's', 'ض': 'z', 'ط': 't', 'ظ': 'z', | |
| 'غ': 'gh', 'ف': 'f', 'ق': 'q', 'ک': 'k', 'ګ': 'g', | |
| 'ل': 'l', 'م': 'm', 'ن': 'n', 'ڼ': 'n', | |
| 'و': 'w', 'ؤ': 'o', 'ه': 'h', 'ۀ': 'a', 'ة': 'a', | |
| 'ي': 'y', 'ې': 'e', 'ی': 'i', 'ئ': 'y', 'ى': 'a', | |
| # Diacritics and special marks | |
| 'َ': 'a', 'ُ': 'u', 'ِ': 'i', 'ً': 'an', 'ٌ': 'un', 'ٍ': 'in', | |
| 'ّ': '', 'ْ': '', 'ٔ': '', 'ٰ': 'a', | |
| # Punctuation | |
| ' ': ' ', '،': ',', '؛': ';', '؟': '?', '۔': '.', '!': '!', | |
| '(': '(', ')': ')', '[': '[', ']': ']', '{': '{', '}': '}', | |
| '-': '-', '_': '_', '«': '"', '»': '"', '"': '"', '"': '"', | |
| # Numbers (Pashto/Arabic numerals to Roman) | |
| '۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4', | |
| '۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9', | |
| '٠': '0', '١': '1', '٢': '2', '٣': '3', '٤': '4', | |
| '٥': '5', '٦': '6', '٧': '7', '٨': '8', '٩': '9', | |
| } | |
| # Transliterate Pashto to Roman | |
| roman_text = '' | |
| for char in pashto_text: | |
| roman_text += pashto_to_roman.get(char, char) | |
| # Clean up extra spaces and formatting | |
| roman_text = ' '.join(roman_text.split()) | |
| return roman_text if roman_text.strip() else pashto_text | |
| # ================================ | |
| # MAIN APPLICATION | |
| # ================================ | |
| def main(): | |
| # Initialize session state | |
| if 'translation_output' not in st.session_state: | |
| st.session_state.translation_output = "" | |
| if 'urdu_input' not in st.session_state: | |
| st.session_state.urdu_input = "" | |
| # Load custom CSS | |
| load_css() | |
| # Header | |
| st.markdown('<h1 class="main-title">🌐 Urdu to Pashto Translator</h1>', unsafe_allow_html=True) | |
| st.markdown('<p class="subtitle">Convert Urdu sentences to Pashto in Roman script</p>', unsafe_allow_html=True) | |
| # Main container | |
| st.markdown('<div class="glass-container">', unsafe_allow_html=True) | |
| # Create two columns for input and output | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown("### 📝 Input (Urdu)") | |
| urdu_input = st.text_area( | |
| "Enter Urdu text", | |
| value=st.session_state.urdu_input, | |
| height=250, | |
| placeholder="یہاں اردو متن درج کریں... (Enter Urdu text here...)", | |
| label_visibility="collapsed", | |
| key="urdu_input_area" | |
| ) | |
| with col2: | |
| st.markdown("### 🔤 Output (Pashto in Roman)") | |
| st.text_area( | |
| "Pashto translation in Roman script", | |
| value=st.session_state.translation_output, | |
| height=250, | |
| placeholder="Translation will appear here...", | |
| label_visibility="collapsed", | |
| key="output_ |