Spaces:
Sleeping
Sleeping
import gradio as gr | |
import requests | |
import html | |
import os | |
# LibreTranslate instance | |
API_URL = "https://imsidag-community-libretranslate-kabyle.hf.space/translate" | |
API_KEY = os.environ["API_KEY"] | |
# Language codes | |
langs = { | |
"English": "en", | |
"French": "fr", | |
"Italian": "it", | |
"Occitan (26000)": "oc_comp2", | |
"Taqbaylit (LTCommunity)": "kab", | |
"Taqbaylit (latest)": "kab_kab", | |
"Taqbaylit (Tasenselkimt)": "kab_comp", | |
"Taqbaylit (51000)": "kab_comp2", | |
"Taqbaylit (OS)": "kab_os", | |
"Taqbaylit (num)": "kab_num", | |
"Taqbaylit (Google)": "google", | |
"Taqbaylit (All Variants)": "kab_all" | |
} | |
kabyle_variants = { | |
"Taqbaylit (LTCommunity)": "kab", | |
"Taqbaylit (latest)": "kab_kab", | |
"Taqbaylit (Tasenselkimt)": "kab_comp", | |
"Taqbaylit (51000)": "kab_comp2", | |
"Taqbaylit (OS)": "kab_os", | |
"Taqbaylit (num)": "kab_num", | |
"Taqbaylit (Google)": "google" | |
} | |
def highlight_differences(translations_dict): | |
token_lists = {k: v.split() for k, v in translations_dict.items()} | |
max_len = max(len(tokens) for tokens in token_lists.values()) | |
aligned = {k: [] for k in token_lists.keys()} | |
for i in range(max_len): | |
words_at_i = [token_lists[k][i] if i < len(token_lists[k]) else "" for k in token_lists] | |
if len(set(words_at_i)) == 1: | |
for k in token_lists: | |
aligned[k].append(words_at_i[0]) | |
else: | |
for k in token_lists: | |
word = token_lists[k][i] if i < len(token_lists[k]) else "" | |
# Use gold color for highlights that works in both themes | |
highlighted = f"<span style='color:#FFD700; font-weight:bold'>{word}</span>" | |
aligned[k].append(highlighted) | |
return {k: " ".join(tokens) for k, tokens in aligned.items()} | |
def translate(text, source_lang, target_lang): | |
source_code = langs.get(source_lang, "en") | |
target_code = langs.get(target_lang) | |
if target_code == "kab_all": | |
# Escape and format the original text with dark-theme friendly styling | |
escaped_text = html.escape(text).replace('\n', '<br>') | |
header = f""" | |
<div style=' | |
margin-bottom: 25px; | |
padding: 15px; | |
border-radius: 8px; | |
background-color: rgba(120, 120, 120, 0.15); | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
'> | |
<div style='font-size: 0.9em; opacity: 0.8; margin-bottom: 5px;'>ORIGINAL TEXT</div> | |
<div style='font-size: 1.1em;'>{escaped_text}</div> | |
<div style='margin-top: 8px; font-size: 0.85em; opacity: 0.7;'> | |
From: {source_lang} → To: {target_lang} | |
</div> | |
</div> | |
""" | |
translations_dict = {} | |
alternatives_dict = {} | |
for name, code in kabyle_variants.items(): | |
if code == "google": | |
# Fallback source for Google | |
google_source = source_code if source_code in ["en", "fr", "it", "es"] else "fr" | |
params = { | |
"engine": "google", | |
"from": google_source, | |
"to": "ber-Latn", | |
"text": text | |
} | |
try: | |
response = requests.get("https://mozhi.pussthecat.org/api/translate", params=params) | |
result = response.json() | |
translations_dict[name] = result.get("translated-text", "<i>No result</i>") | |
alternatives_dict[name] = "" | |
except Exception as e: | |
translations_dict[name] = f"<i>Google Error: {str(e)}</i>" | |
alternatives_dict[name] = "" | |
else: | |
data = { | |
"q": text, | |
"source": source_code, | |
"target": code, | |
"format": "text", | |
"alternatives": 3, | |
"api_key": API_KEY | |
} | |
try: | |
response = requests.post(API_URL, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"}) | |
result = response.json() | |
if "translatedText" in result: | |
translations_dict[name] = result["translatedText"] | |
alternatives_dict[name] = ", ".join(result.get("alternatives", [])) | |
elif "error" in result: | |
translations_dict[name] = f"<i>API Error: {result['error']}</i>" | |
alternatives_dict[name] = "" | |
else: | |
translations_dict[name] = "<i>Unexpected response</i>" | |
alternatives_dict[name] = "" | |
except Exception as e: | |
translations_dict[name] = f"<i>Exception: {str(e)}</i>" | |
alternatives_dict[name] = "" | |
highlighted = highlight_differences(translations_dict) | |
outputs = [] | |
for name in kabyle_variants: | |
output = f"<div style='margin-bottom: 15px;'><b>{name}</b>:<br>Translation: {highlighted[name]}" | |
if alternatives_dict.get(name): | |
output += f"<br>Alternatives: <span style='opacity:0.8;'>{alternatives_dict[name]}</span>" | |
output += "</div>" | |
outputs.append(output) | |
return header + "".join(outputs) | |
elif target_code == "google": | |
google_source = source_code if source_code in ["en", "fr", "it", "es"] else "fr" | |
params = { | |
"engine": "google", | |
"from": google_source, | |
"to": "ber-Latn", | |
"text": text | |
} | |
try: | |
response = requests.get("https://mozhi.pussthecat.org/api/translate", params=params) | |
result = response.json() | |
return f"<b>Translation:</b> {result.get('translated-text', '<i>No result</i>')}" | |
except Exception as e: | |
return f"<i>Google Error: {str(e)}</i>" | |
else: | |
data = { | |
"q": text, | |
"source": source_code, | |
"target": target_code, | |
"format": "text", | |
"alternatives": 3, | |
"api_key": API_KEY | |
} | |
try: | |
response = requests.post(API_URL, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"}) | |
result = response.json() | |
if "translatedText" in result: | |
output = f"<b>Translation:</b> {result['translatedText']}" | |
if result.get("alternatives"): | |
alt = ", ".join(result["alternatives"]) | |
output += f"<br><b>Alternatives:</b> {alt}" | |
return output | |
elif "error" in result: | |
return f"<i>API Error: {result['error']}</i>" | |
else: | |
return f"<i>Unexpected response: {result}</i>" | |
except Exception as e: | |
return f"<i>Exception: {str(e)}</i>" | |
# Gradio UI with dark theme friendly styling | |
with gr.Blocks(theme=gr.themes.Default()) as demo: | |
gr.Markdown("# Kabyle Translator") | |
gr.Markdown("Compare Kabyle translations from LibreTranslate (variants) and Google Translate via Mozhi. Differences are highlighted.") | |
with gr.Row(): | |
with gr.Column(): | |
input_text = gr.Textbox(label="Enter text to translate", lines=3) | |
source_lang = gr.Dropdown(choices=list(langs.keys()), label="From language", value="English") | |
target_lang = gr.Dropdown(choices=list(langs.keys()), label="To language", value="Taqbaylit (All Variants)") | |
submit_btn = gr.Button("Translate") | |
with gr.Column(): | |
output = gr.HTML(label="Translation Results") | |
submit_btn.click( | |
fn=translate, | |
inputs=[input_text, source_lang, target_lang], | |
outputs=output | |
) | |
demo.launch() |