File size: 9,630 Bytes
737c030 e656608 da34b5e 35cccff f3041d7 891f160 b5c7107 c55f7e1 aa9d2fe b5c7107 ff5aa1c 8040f65 b5c7107 40d3704 35cccff 40d3704 b5c7107 40d3704 b5c7107 40d3704 b5c7107 35cccff b5c7107 35cccff b5c7107 3432325 b5c7107 3432325 40d3704 891f160 ff5aa1c b5c7107 40d3704 e656608 b5c7107 ff5aa1c 7d2b4d7 b5c7107 7d2b4d7 b5c7107 63de0ad b5c7107 63de0ad c55f7e1 b5c7107 63de0ad b5c7107 54945d2 b5c7107 7d2b4d7 8040f65 b5c7107 40d3704 b5c7107 40d3704 c55f7e1 538b10c 40d3704 63de0ad 3432325 f6b831a 3432325 54945d2 40d3704 b5c7107 35cccff 95432d5 ff5aa1c 63de0ad b5c7107 6c6d6f8 b5c7107 c55f7e1 ff5aa1c b5c7107 1549aa1 b5c7107 40d3704 b5c7107 1549aa1 b5c7107 40d3704 b5c7107 8040f65 891f160 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
import streamlit as st
import importlib
from io import BytesIO
import docx
from PyPDF2 import PdfReader
import time
# Configure Streamlit page settings
st.set_page_config(page_title="Multilingual Translator", page_icon="π", layout="wide")
# Import language definitions from translation module
try:
from translation import LANGUAGES
except ImportError as e:
st.error(f"Failed to import translation module: {e}")
st.stop()
# Extract text from uploaded files (PDF, DOCX, TXT)
def extract_text_from_file(uploaded_file):
try:
if uploaded_file.type == "application/pdf":
pdf_reader = PdfReader(uploaded_file)
text = "".join(page.extract_text() or "" for page in pdf_reader.pages)
return text.encode().decode("utf-8", errors="ignore").strip()
elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
doc = docx.Document(uploaded_file)
text = "\n".join(para.text for para in doc.paragraphs)
return text.encode().decode("utf-8", errors="ignore").strip()
elif uploaded_file.type == "text/plain":
return uploaded_file.read().decode("utf-8", errors="ignore").strip()
return ""
except Exception as e:
st.error(f"Error extracting text from file: {e}")
return ""
# Update input text when a file is uploaded
def on_file_upload():
try:
uploaded_file = st.session_state.get("file_input")
if uploaded_file and uploaded_file.size < 1024 * 1024:
st.session_state.user_input_text = extract_text_from_file(uploaded_file)
st.success(f"File '{uploaded_file.name}' uploaded successfully!")
elif uploaded_file and uploaded_file.size >= 1024 * 1024:
st.error("File size must be less than 1 MB")
except Exception as e:
st.error(f"Error processing file upload: {e}")
# Main application function
def main():
try:
# Import required modules dynamically
translation_module = importlib.import_module("translation")
language_detector = importlib.import_module("lang_detect")
audio_processor_module = importlib.import_module("audio_processor")
# Display application header
st.markdown("<h1 style='text-align: center; color: #4285F4;'>Multilingual Translator</h1>", unsafe_allow_html=True)
st.markdown("<p style='text-align: center; color: #666;'>Effortless Multilingual Translation</p>", unsafe_allow_html=True)
# Apply custom CSS for UI enhancements
st.markdown(
"""
<style>
.stFileUploader > div > div > div[role="button"] { display: none !important; }
.stFileUploader label { display: none !important; }
.stFileUploader [data-testid="stFileUploaderDropzone"] {
border: 2px dashed #ccc !important; padding: 10px !important;
text-align: center !important; font-size: 0 !important;
}
.stFileUploader [data-testid="stFileUploaderDropzone"]::after {
content: 'Drag and drop TXT, DOCX, or PDF here or ' !important;
font-size: 1em !important; color: #666 !important;
}
.stFileUploader [data-testid="stFileUploaderButton"] {
font-size: 1em !important; color: #1E90FF !important;
background: none !important; border: none !important; padding: 0 !important;
}
.stFileUploader [data-testid="stFileUploader"] { background: none !important; }
.stRadio > div { margin-bottom: 0 !important; }
.stTextArea { margin-top: 0 !important; }
</style>
""",
unsafe_allow_html=True
)
# Create symmetric layout with two columns
left_col, right_col = st.columns([1, 1])
with left_col:
# Detect language of input text if available
detected_options = language_detector.detect_language(st.session_state.get("user_input_text", "").strip()) if st.session_state.get("user_input_text", "").strip() else [("Auto-detect", 1.0, "Auto-detect")]
source_language = detected_options[0][2] if detected_options[0][0] != "Auto-detect" else "Auto-detect"
source_lang_code = next((k for k, v in LANGUAGES.items() if v[1] == source_language), "en") if source_language != "Auto-detect" else "auto"
source_options = ["Auto-detect"] + [f"{v[0]} ({v[1]})" for v in LANGUAGES.values()]
st.selectbox("Source Language", options=source_options, index=0 if source_language == "Auto-detect" else source_options.index(f"{LANGUAGES[source_lang_code][0]} ({source_language})"), key="source_lang")
user_input_text = st.text_area("Input Text", height=200, key="user_input_text", placeholder="Enter text here", label_visibility="hidden")
input_type = st.radio("Input Type", ["Text", "File"], horizontal=True, label_visibility="hidden", key="input_type")
if input_type == "File":
st.file_uploader("Upload File", type=["txt", "docx", "pdf"], key="file_input", on_change=on_file_upload, label_visibility="hidden")
st.button("Translate", key="translate_btn", on_click=trigger_translation, args=(translation_module, language_detector, audio_processor_module))
with right_col:
# Set target language options based on source language
source_lang_display = st.session_state.source_lang.split(" (")[0] if " (" in st.session_state.source_lang else st.session_state.source_lang
target_options = [f"{v[0]} ({v[1]})" for v in LANGUAGES.values() if v[0] != source_lang_display and v[1] != source_lang_display]
st.selectbox("Target Language", options=target_options, index=target_options.index(f"{LANGUAGES['en'][0]} ({LANGUAGES['en'][1]})") if "English" not in source_lang_display else 0, key="target_lang")
if "translated_text" in st.session_state:
st.text_area("Output Text", value=st.session_state.translated_text, height=200, key="output_text", disabled=True, label_visibility="hidden")
# Trigger audio playback on button click
if st.button("π", key="audio_btn", on_click=play_audio, args=(audio_processor_module,), help="Play audio", use_container_width=False):
pass
# Display application footer
st.markdown("""
<p style="font-size: small; color: grey; text-align: center;">
Developed By: Krishna Prakash
<a href="https://www.linkedin.com/in/krishnaprakash-profile/" target="_blank">
<img src="https://img.icons8.com/ios-filled/30/0077b5/linkedin.png" alt="LinkedIn" style="vertical-align: middle; margin: 0 5px;"/>
</a>
</p>
""", unsafe_allow_html=True)
except Exception as e:
st.error(f"Application error occurred: {e}")
# Trigger translation process with timeout handling
def trigger_translation(translation_module, language_detector, audio_processor_module):
try:
user_input_text = st.session_state.get("user_input_text", "").strip()
if user_input_text:
with st.spinner("Translating..."):
start_time = time.time()
source_lang = st.session_state.source_lang.split(" (")[0] if " (" in st.session_state.source_lang else st.session_state.source_lang
target_lang = st.session_state.target_lang.split(" (")[0] if " (" in st.session_state.target_lang else st.session_state.target_lang
if source_lang == "Auto-detect":
detected_options = language_detector.detect_language(user_input_text)
source_lang_code = next((k for k, v in LANGUAGES.items() if v[1] == detected_options[0][0]), "en")
else:
source_lang_code = next((k for k, v in LANGUAGES.items() if v[0] == source_lang), "en")
target_lang_code = next((k for k, v in LANGUAGES.items() if v[0] == target_lang), "en")
translated_text = translation_module.translate(user_input_text, source_lang_code, target_lang_code)
if time.time() - start_time > 20: # Check if translation exceeds 20-second timeout
st.error("Translation took too long, reverting to input.")
translated_text = user_input_text
if translated_text and len(translated_text.split()) > 2: # Validate translation result
st.session_state.translated_text = translated_text
else:
st.session_state.translated_text = user_input_text
except Exception as e:
st.error(f"Translation process failed: {e}")
st.session_state.translated_text = user_input_text
# Handle audio playback with error checking
def play_audio(audio_processor_module):
try:
if "translated_text" in st.session_state and st.session_state.translated_text:
target_lang = next((k for k, v in LANGUAGES.items() if v[0] == st.session_state.target_lang.split(" (")[0]), "en")
audio_data = audio_processor_module.text_to_speech(st.session_state.translated_text, target_lang)
if audio_data and audio_data.getbuffer().nbytes > 0:
st.audio(audio_data, format="audio/mp3")
else:
st.error("Failed to generate audio. Please try again.")
except Exception as e:
st.error(f"Audio playback failed: {e}")
if __name__ == "__main__":
main() |