File size: 9,207 Bytes
737c030 e656608 da34b5e 35cccff f3041d7 891f160 c55f7e1 aa9d2fe ff5aa1c 8040f65 40d3704 35cccff 40d3704 35cccff 40d3704 35cccff 40d3704 35cccff 40d3704 3432325 40d3704 c55f7e1 3432325 40d3704 891f160 ff5aa1c 40d3704 e656608 ff5aa1c 7d2b4d7 54945d2 7d2b4d7 cff3443 7d2b4d7 c55f7e1 7d2b4d7 63de0ad c55f7e1 63de0ad c55f7e1 63de0ad c55f7e1 63de0ad 54945d2 7d2b4d7 8040f65 c55f7e1 40d3704 c55f7e1 538b10c 40d3704 63de0ad 3432325 f6b831a 3432325 54945d2 40d3704 35cccff 95432d5 ff5aa1c 63de0ad 6c6d6f8 35cccff c55f7e1 ff5aa1c 1549aa1 926dcae 40d3704 cff3443 f3041d7 cff3443 c55f7e1 cff3443 63de0ad cff3443 926dcae f3041d7 c55f7e1 1549aa1 4f6d7d9 40d3704 1549aa1 538b10c 40d3704 4f6d7d9 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 164 165 166 167 |
import streamlit as st
import importlib
from io import BytesIO
import docx
from PyPDF2 import PdfReader
import time
st.set_page_config(page_title="Multilingual Translator", page_icon="π", layout="wide")
# Import LANGUAGES from translation.py
try:
from translation import LANGUAGES
except ImportError as e:
st.error(f"Failed to import translation module: {e}")
st.stop()
# Function to 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 = ""
for page in pdf_reader.pages:
text += page.extract_text() or ""
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:
return ""
# Callback to update input text when file is uploaded
def on_file_upload():
uploaded_file = st.session_state.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")
# Main application function
def main():
try:
translation_module = importlib.import_module("translation")
language_detector = importlib.import_module("lang_detect")
audio_processor_module = importlib.import_module("audio_processor")
# 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)
# Custom CSS to hide size limit and white box, reduce spacing
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
)
# Language and Input/Output Layout with symmetric columns
left_col, right_col = st.columns([1, 1]) # Equal width for symmetric layout
with left_col:
detected_options = language_detector.detect_language(st.session_state.get("user_input_text", "")) 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:
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")
# Play audio button and playback below output
if st.button("π", key="audio_btn", on_click=play_audio, args=(audio_processor_module,), help="Play audio", use_container_width=False):
pass
# 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"App error: {e}")
# Function to trigger translation process with progress indicator and adjusted timeout
def trigger_translation(translation_module, language_detector, audio_processor_module):
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), "hi")
translated_text = translation_module.translate(user_input_text, source_lang_code, target_lang_code)
if time.time() - start_time > 15: # Increased timeout to 15 seconds
st.error("Translation took too long, reverting to input.")
translated_text = user_input_text
if translated_text and len(translated_text.split()) > 2: # Basic validation
st.session_state.translated_text = translated_text
else:
st.session_state.translated_text = user_input_text
# Function to handle audio playback with error handling
def play_audio(audio_processor_module):
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.")
if __name__ == "__main__":
main() |