Spaces:
Runtime error
Runtime error
| """ | |
| CodeAlpha - Task 1: Language Translation Tool | |
| Author: (Loic HOUNYOVI) | |
| Description: Application web permettant de traduire du texte d'une langue | |
| source vers une langue cible en utilisant un vrai modèle de | |
| deep learning (Meta NLLB-200) chargé localement via la | |
| librairie Hugging Face `transformers`, avec en bonus une | |
| synthèse vocale (text-to-speech) et un bouton copier. | |
| Modèle utilisé : facebook/nllb-200-distilled-600M | |
| - Modèle Seq2Seq (encoder-decoder) multilingue, pré-entraîné par Meta AI | |
| - Supporte ~200 langues avec un seul et même modèle | |
| - Chargé via transformers.pipeline("translation", ...) | |
| """ | |
| import io | |
| import streamlit as st | |
| from transformers import AutoModelForSeq2SeqLM, AutoTokenizer | |
| from gtts import gTTS | |
| try: | |
| from langdetect import detect as detect_lang | |
| LANGDETECT_AVAILABLE = True | |
| except ImportError: | |
| LANGDETECT_AVAILABLE = False | |
| # --------------------------------------------------------- | |
| # Configuration de la page | |
| st.set_page_config( | |
| page_title="CodeAlpha Language Translator (AI Model)", | |
| page_icon="🌐", | |
| layout="centered", | |
| ) | |
| # --------------------------------------------------------- | |
| # Langues supportées : code affichage -> (code NLLB / FLORES-200, code gTTS) | |
| LANGUAGES = { | |
| "en": "Anglais", | |
| "fr": "Français", | |
| "es": "Espagnol", | |
| "de": "Allemand", | |
| "it": "Italien", | |
| "pt": "Portugais", | |
| "ar": "Arabe", | |
| "zh-CN": "Chinois (simplifié)", | |
| "ja": "Japonais", | |
| "ko": "Coréen", | |
| "ru": "Russe", | |
| "hi": "Hindi", | |
| "nl": "Néerlandais", | |
| "tr": "Turc", | |
| } | |
| NLLB_CODES = { | |
| "en": "eng_Latn", | |
| "fr": "fra_Latn", | |
| "es": "spa_Latn", | |
| "de": "deu_Latn", | |
| "it": "ita_Latn", | |
| "pt": "por_Latn", | |
| "ar": "arb_Arab", | |
| "zh-CN": "zho_Hans", | |
| "ja": "jpn_Jpan", | |
| "ko": "kor_Hang", | |
| "ru": "rus_Cyrl", | |
| "hi": "hin_Deva", | |
| "nl": "nld_Latn", | |
| "tr": "tur_Latn", | |
| } | |
| # gTTS accepte directement des codes ISO classiques (tous nos codes conviennent) | |
| TTS_SUPPORTED = set(LANGUAGES.keys()) | |
| # --------------------------------------------------------- | |
| # Chargement du modèle (mis en cache : ne se recharge pas à chaque interaction) | |
| MODEL_NAME = "facebook/nllb-200-distilled-600M" | |
| def load_model(): | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) | |
| model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME) | |
| return tokenizer, model | |
| def translate_text(text: str, src_code: str, tgt_code: str) -> str: | |
| """Traduit `text` de src_code vers tgt_code (codes FLORES-200) via NLLB-200.""" | |
| tokenizer, model = load_model() | |
| tokenizer.src_lang = src_code | |
| inputs = tokenizer(text, return_tensors="pt", truncation=True) | |
| forced_bos_token_id = tokenizer.convert_tokens_to_ids(tgt_code) | |
| generated_tokens = model.generate( | |
| **inputs, | |
| forced_bos_token_id=forced_bos_token_id, | |
| max_length=400, | |
| ) | |
| return tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)[0] | |
| # --------------------------------------------------------- | |
| # En-tête | |
| st.title("🌐 Language Translation Tool") | |
| st.caption("CodeAlpha Artificial Intelligence Internship — Task 1") | |
| st.write( | |
| "Entrez votre texte, choisissez la langue source et la langue cible, " | |
| "puis cliquez sur **Traduire**." | |
| ) | |
| # --------------------------------------------------------- | |
| # Zone de saisie | |
| input_text = st.text_area("Texte à traduire :", height=150, placeholder="Écrivez ou collez votre texte ici...") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| source_options = ["auto"] + list(LANGUAGES.keys()) if LANGDETECT_AVAILABLE else list(LANGUAGES.keys()) | |
| source_lang = st.selectbox( | |
| "Langue source", | |
| options=source_options, | |
| format_func=lambda code: "Détection automatique" if code == "auto" else LANGUAGES[code], | |
| index=0, | |
| ) | |
| with col2: | |
| # Langue cible par défaut : anglais si la source n'est pas anglais, sinon français | |
| target_options = [c for c in LANGUAGES.keys() if c != "auto"] | |
| target_lang = st.selectbox( | |
| "Langue cible", | |
| options=target_options, | |
| format_func=lambda code: LANGUAGES[code], | |
| index=target_options.index("fr") if "fr" in target_options else 0, | |
| ) | |
| translate_clicked = st.button("🔄 Traduire", type="primary", use_container_width=True) | |
| # --------------------------------------------------------- | |
| # Logique de traduction | |
| if "translated_text" not in st.session_state: | |
| st.session_state.translated_text = "" | |
| if translate_clicked: | |
| if not input_text.strip(): | |
| st.warning("Merci d'entrer du texte avant de traduire.") | |
| else: | |
| try: | |
| # --- Détection automatique de la langue source si demandé --- | |
| actual_source = source_lang | |
| if source_lang == "auto": | |
| if LANGDETECT_AVAILABLE: | |
| detected = detect_lang(input_text) | |
| # langdetect renvoie parfois "zh-cn" au lieu de "zh-CN" | |
| detected = "zh-CN" if detected.lower().startswith("zh") else detected | |
| actual_source = detected if detected in LANGUAGES else "en" | |
| else: | |
| actual_source = "en" | |
| src_code = NLLB_CODES.get(actual_source) | |
| tgt_code = NLLB_CODES.get(target_lang) | |
| if src_code is None or tgt_code is None: | |
| st.error("Langue non supportée par le modèle.") | |
| else: | |
| with st.spinner("Traduction en cours (inférence du modèle)..."): | |
| result = translate_text(input_text, src_code, tgt_code) | |
| st.session_state.translated_text = result | |
| if source_lang == "auto": | |
| st.caption(f"🔍 Langue détectée : {LANGUAGES.get(actual_source, actual_source)}") | |
| except Exception as e: | |
| st.error(f"Une erreur est survenue lors de la traduction : {e}") | |
| # --------------------------------------------------------- | |
| # Affichage du résultat | |
| if st.session_state.translated_text: | |
| st.subheader("Traduction :") | |
| st.text_area( | |
| "Résultat", | |
| value=st.session_state.translated_text, | |
| height=150, | |
| label_visibility="collapsed", | |
| ) | |
| col_a, col_b = st.columns(2) | |
| # --- Bouton copier (via un petit composant HTML/JS) --- | |
| with col_a: | |
| copy_html = f""" | |
| <textarea id="toCopy" style="display:none;">{st.session_state.translated_text}</textarea> | |
| <button onclick="navigator.clipboard.writeText(document.getElementById('toCopy').value)" | |
| style="width:100%; padding:8px; border-radius:6px; border:1px solid #ccc; cursor:pointer;"> | |
| 📋 Copier le texte | |
| </button> | |
| """ | |
| st.components.v1.html(copy_html, height=45) | |
| # --- Bouton text-to-speech --- | |
| with col_b: | |
| if target_lang in TTS_SUPPORTED: | |
| if st.button("🔊 Écouter la traduction", use_container_width=True): | |
| try: | |
| tts = gTTS(text=st.session_state.translated_text, lang=target_lang) | |
| audio_bytes = io.BytesIO() | |
| tts.write_to_fp(audio_bytes) | |
| audio_bytes.seek(0) | |
| st.audio(audio_bytes, format="audio/mp3") | |
| except Exception as e: | |
| st.error(f"Impossible de générer l'audio : {e}") | |
| else: | |
| st.info("🔇 Audio non disponible pour cette langue.") | |
| # --------------------------------------------------------- | |
| # Pied de page | |
| st.divider() | |
| st.caption("Projet réalisé dans le cadre du stage AI @CodeAlpha") | |