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 (Tasenselkimt)": "kab_comp",
"Taqbaylit (51000)": "kab_comp2",
"Taqbaylit (OS)": "kab_os",
"Taqbaylit (Google)": "google",
"Taqbaylit (All Variants)": "kab_all"
}
kabyle_variants = {
"Taqbaylit (LTCommunity)": "kab",
"Taqbaylit (Tasenselkimt)": "kab_comp",
"Taqbaylit (51000)": "kab_comp2",
"Taqbaylit (OS)": "kab_os",
"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"{word}"
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', '
')
header = f"""
ORIGINAL TEXT
{escaped_text}
From: {source_lang} → To: {target_lang}
"""
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", "No result")
alternatives_dict[name] = ""
except Exception as e:
translations_dict[name] = f"Google Error: {str(e)}"
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"API Error: {result['error']}"
alternatives_dict[name] = ""
else:
translations_dict[name] = "Unexpected response"
alternatives_dict[name] = ""
except Exception as e:
translations_dict[name] = f"Exception: {str(e)}"
alternatives_dict[name] = ""
highlighted = highlight_differences(translations_dict)
outputs = []
for name in kabyle_variants:
output = f"{name}:
Translation: {highlighted[name]}"
if alternatives_dict.get(name):
output += f"
Alternatives: {alternatives_dict[name]}"
output += "
"
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"Translation: {result.get('translated-text', 'No result')}"
except Exception as e:
return f"Google Error: {str(e)}"
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"Translation: {result['translatedText']}"
if result.get("alternatives"):
alt = ", ".join(result["alternatives"])
output += f"
Alternatives: {alt}"
return output
elif "error" in result:
return f"API Error: {result['error']}"
else:
return f"Unexpected response: {result}"
except Exception as e:
return f"Exception: {str(e)}"
# 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()