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()