axxam commited on
Commit
4c14a5a
·
verified ·
1 Parent(s): 8125d76

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +197 -0
app.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import html
4
+ import os
5
+
6
+ # LibreTranslate instance
7
+ API_URL = "https://axxam-libretranslate-kabyle.hf.space/translate"
8
+ API_KEY = os.environ["API_KEY"]
9
+
10
+ # Language codes
11
+ langs = {
12
+ "English": "en",
13
+ "French": "fr",
14
+ "Italian": "it",
15
+ "Occitan (26000)": "oc_comp2",
16
+ "Taqbaylit (LTCommunity)": "kab",
17
+ "Taqbaylit (Tasenselkimt)": "kab_comp",
18
+ "Taqbaylit (51000)": "kab_comp2",
19
+ "Taqbaylit (Google)": "google",
20
+ "Taqbaylit (All Variants)": "kab_all"
21
+ }
22
+
23
+ kabyle_variants = {
24
+ "Taqbaylit (LTCommunity)": "kab",
25
+ "Taqbaylit (Tasenselkimt)": "kab_comp",
26
+ "Taqbaylit (51000)": "kab_comp2",
27
+ "Taqbaylit (Google)": "google"
28
+ }
29
+
30
+ def highlight_differences(translations_dict):
31
+ token_lists = {k: v.split() for k, v in translations_dict.items()}
32
+ max_len = max(len(tokens) for tokens in token_lists.values())
33
+ aligned = {k: [] for k in token_lists.keys()}
34
+
35
+ for i in range(max_len):
36
+ words_at_i = [token_lists[k][i] if i < len(token_lists[k]) else "" for k in token_lists]
37
+ if len(set(words_at_i)) == 1:
38
+ for k in token_lists:
39
+ aligned[k].append(words_at_i[0])
40
+ else:
41
+ for k in token_lists:
42
+ word = token_lists[k][i] if i < len(token_lists[k]) else ""
43
+ # Use gold color for highlights that works in both themes
44
+ highlighted = f"<span style='color:#FFD700; font-weight:bold'>{word}</span>"
45
+ aligned[k].append(highlighted)
46
+
47
+ return {k: " ".join(tokens) for k, tokens in aligned.items()}
48
+
49
+
50
+ def translate(text, source_lang, target_lang):
51
+ source_code = langs.get(source_lang, "en")
52
+ target_code = langs.get(target_lang)
53
+
54
+ if target_code == "kab_all":
55
+ # Escape and format the original text with dark-theme friendly styling
56
+ escaped_text = html.escape(text).replace('\n', '<br>')
57
+ header = f"""
58
+ <div style='
59
+ margin-bottom: 25px;
60
+ padding: 15px;
61
+ border-radius: 8px;
62
+ background-color: rgba(120, 120, 120, 0.15);
63
+ border: 1px solid rgba(255, 255, 255, 0.1);
64
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
65
+ '>
66
+ <div style='font-size: 0.9em; opacity: 0.8; margin-bottom: 5px;'>ORIGINAL TEXT</div>
67
+ <div style='font-size: 1.1em;'>{escaped_text}</div>
68
+ <div style='margin-top: 8px; font-size: 0.85em; opacity: 0.7;'>
69
+ From: {source_lang} → To: {target_lang}
70
+ </div>
71
+ </div>
72
+ """
73
+
74
+ translations_dict = {}
75
+ alternatives_dict = {}
76
+
77
+ for name, code in kabyle_variants.items():
78
+ if code == "google":
79
+ # Fallback source for Google
80
+ google_source = source_code if source_code in ["en", "fr", "it", "es"] else "fr"
81
+ params = {
82
+ "engine": "google",
83
+ "from": google_source,
84
+ "to": "ber-Latn",
85
+ "text": text
86
+ }
87
+ try:
88
+ response = requests.get("https://mozhi.pussthecat.org/api/translate", params=params)
89
+ result = response.json()
90
+ translations_dict[name] = result.get("translated-text", "<i>No result</i>")
91
+ alternatives_dict[name] = ""
92
+ except Exception as e:
93
+ translations_dict[name] = f"<i>Google Error: {str(e)}</i>"
94
+ alternatives_dict[name] = ""
95
+ else:
96
+ data = {
97
+ "q": text,
98
+ "source": source_code,
99
+ "target": code,
100
+ "format": "text",
101
+ "alternatives": 3,
102
+ "api_key": API_KEY
103
+ }
104
+ try:
105
+ response = requests.post(API_URL, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"})
106
+ result = response.json()
107
+
108
+ if "translatedText" in result:
109
+ translations_dict[name] = result["translatedText"]
110
+ alternatives_dict[name] = ", ".join(result.get("alternatives", []))
111
+ elif "error" in result:
112
+ translations_dict[name] = f"<i>API Error: {result['error']}</i>"
113
+ alternatives_dict[name] = ""
114
+ else:
115
+ translations_dict[name] = "<i>Unexpected response</i>"
116
+ alternatives_dict[name] = ""
117
+ except Exception as e:
118
+ translations_dict[name] = f"<i>Exception: {str(e)}</i>"
119
+ alternatives_dict[name] = ""
120
+
121
+ highlighted = highlight_differences(translations_dict)
122
+
123
+ outputs = []
124
+ for name in kabyle_variants:
125
+ output = f"<div style='margin-bottom: 15px;'><b>{name}</b>:<br>Translation: {highlighted[name]}"
126
+ if alternatives_dict.get(name):
127
+ output += f"<br>Alternatives: <span style='opacity:0.8;'>{alternatives_dict[name]}</span>"
128
+ output += "</div>"
129
+ outputs.append(output)
130
+
131
+ return header + "".join(outputs)
132
+
133
+ elif target_code == "google":
134
+ google_source = source_code if source_code in ["en", "fr", "it", "es"] else "fr"
135
+ params = {
136
+ "engine": "google",
137
+ "from": google_source,
138
+ "to": "ber-Latn",
139
+ "text": text
140
+ }
141
+ try:
142
+ response = requests.get("https://mozhi.pussthecat.org/api/translate", params=params)
143
+ result = response.json()
144
+ return f"<b>Translation:</b> {result.get('translated-text', '<i>No result</i>')}"
145
+ except Exception as e:
146
+ return f"<i>Google Error: {str(e)}</i>"
147
+
148
+ else:
149
+ data = {
150
+ "q": text,
151
+ "source": source_code,
152
+ "target": target_code,
153
+ "format": "text",
154
+ "alternatives": 3,
155
+ "api_key": API_KEY
156
+ }
157
+
158
+ try:
159
+ response = requests.post(API_URL, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"})
160
+ result = response.json()
161
+
162
+ if "translatedText" in result:
163
+ output = f"<b>Translation:</b> {result['translatedText']}"
164
+ if result.get("alternatives"):
165
+ alt = ", ".join(result["alternatives"])
166
+ output += f"<br><b>Alternatives:</b> {alt}"
167
+ return output
168
+ elif "error" in result:
169
+ return f"<i>API Error: {result['error']}</i>"
170
+ else:
171
+ return f"<i>Unexpected response: {result}</i>"
172
+ except Exception as e:
173
+ return f"<i>Exception: {str(e)}</i>"
174
+
175
+
176
+ # Gradio UI with dark theme friendly styling
177
+ with gr.Blocks(theme=gr.themes.Default()) as demo:
178
+ gr.Markdown("# Kabyle Translator")
179
+ gr.Markdown("Compare Kabyle translations from LibreTranslate (variants) and Google Translate via Mozhi. Differences are highlighted.")
180
+
181
+ with gr.Row():
182
+ with gr.Column():
183
+ input_text = gr.Textbox(label="Enter text to translate", lines=3)
184
+ source_lang = gr.Dropdown(choices=list(langs.keys()), label="From language", value="English")
185
+ target_lang = gr.Dropdown(choices=list(langs.keys()), label="To language", value="Taqbaylit (All Variants)")
186
+ submit_btn = gr.Button("Translate")
187
+
188
+ with gr.Column():
189
+ output = gr.HTML(label="Translation Results")
190
+
191
+ submit_btn.click(
192
+ fn=translate,
193
+ inputs=[input_text, source_lang, target_lang],
194
+ outputs=output
195
+ )
196
+
197
+ demo.launch()