intyoza / static /common.js
konniedeveloping's picture
Update static/common.js
f4d98bd verified
Raw History Blame Contribute Delete
19.5 kB
/* Intyoza shared: theme (light/dark) + interface language (Kinyarwanda default).
Loaded on BOTH the landing page and the chat page.
To translate a new element: <span data-i18n="key"></span>
Also available: data-i18n-html (allows <b>, <br>, <em>), data-i18n-ph (placeholder),
data-i18n-title (tooltip). In JS use: t("key") or t("key",{name:"Aline"}) */
(function () {
"use strict";
const root = document.documentElement;
const I18N = {
/* ===================== KINYARWANDA (default) ===================== */
rw: {
theme_title: "Hindura isura (umucyo / umwijima)",
lang_title: "Hindura ururimi",
/* ---------- landing ---------- */
nav_features: "Ibiranga",
nav_how: "Uko ikora",
nav_pron: "Imivugire",
nav_contact: "Twandikire",
open_app: "Fungura Intyoza",
pill: "Ubu ivuga ikoresheje amasaku n'ubutinde",
h1: "Wige Ikinyarwanda.<br>Witoze Icyongereza.<br><em>Mu biganiro nyabyo.</em>",
lead: "Intyoza ni umufasha wa AI ufite ubwihangane, uhuza n'urwego rwawe, agukosora mu gihe uvuga, kandi avuga Ikinyarwanda nk'uko kivugwa nyabyo, si uko cyanditse.",
cta_start: "Tangira ikiganiro",
cta_see: "Reba uko ikora",
meta1_l: "umwarimu uhuza nawe",
meta2_l: "amagambo afite ibimenyetso",
meta3_n: "Ubuntu",
meta3_l: "kugira ngo utangire",
fc1_l: "Imivugire",
fc2_l: "Uburyo",
fc2_m: "Ihuza n'urwego rwawe",
fc3_l: "Gukosora",
fc3_m: "Buhoro, mu kiganiro",
feat_eyebrow: "Ibyo ubona",
feat_h2: "Yubatswe ku buryo abantu biga ururimi koko.",
f1_h: "Ikiganiro mbere na mbere",
f1_p: "Nta bikarita cyangwa imyitozo irambiranye. Urandika, Intyoza igasubiza, kandi isomo rikaba mu kiganiro.",
f2_h: "Imivugire nyayo",
f2_p: "Amasaku n'ubutinde bigaragaza uburebure bw'inyajwi n'aho ijwi riremera, ku buryo amagambo asomwa nk'uko avugwa.",
f3_h: "Gukosora bifasha",
f3_p: "Amakosa akosorwa mu kiganiro hamwe n'impamvu ngufi, nta kimenyetso gitukura cyangwa amanota.",
f4_h: "Ibiganiro bibikwa",
f4_p: "Buri kiganiro kirabikwa, kigahabwa umutwe ku buryo bwikora, kigategereza aho wari ugeze.",
f5_h: "Mu mpande zombi",
f5_p: "Abavuga Ikinyarwanda bitoza Icyongereza, n'abavuga Icyongereza bakiga Ikinyarwanda, bose bafite umwarimu umwe.",
f6_h: "Itangira vuba",
f6_p: "Fungura utangire kuvuga. Fungura konti gusa igihe ushaka ko amateka yawe abikwa.",
how_eyebrow: "Umwarimu uhuza nawe",
how_h2: "Intyoza ihindura uko ikuvugisha bitewe n'uko wumva.",
s1_tag: "Intangiriro",
s1_h: "Itangirana Ikinyarwanda",
s1_p: "Intyoza ikuvugisha mu Kinyarwanda gusa kuva mu ntangiriro, kugira ngo wumve injyana n'amagambo nyayo.",
s2_tag: "Iyo ugize ikibazo",
s2_h: "Ivanga Icyongereza gike",
s2_p: "Iyo ibonye ko utumva, ikoresha Icyongereza gito kugira ngo igusobanurire, hanyuma igasubira mu Kinyarwanda.",
s3_tag: "Ihuza nawe",
s3_h: "Ikurikira urwego rwawe",
s3_p: "Niba ukomeje kwandika mu Cyongereza, Intyoza yongera Ikinyarwanda buhoro buhoro kugeza igihe witeguriye.",
pron_eyebrow: "Amasaku n'ubutinde",
pron_h2: "Imyandikire y'Ikinyarwanda ihisha uko amagambo avugwa.",
pron_p: "Imyandikire isanzwe ntigaragaza uburebure bw'inyajwi cyangwa ubutinde. Intyoza ifite urutonde rw'amagambo afite ibimenyetso, bityo imenya ko <b>Ababo</b> ivugwa <b>Aba芒bo</b>, ikabikoresha mu kuvuga, kandi ikakwereka ibimenyetso igihe bigufitiye akamaro.",
pron_btn: "Yumve mu kiganiro",
cta_h: "Muraho. Dutangire?",
cta_p: "Fungura Intyoza wandike interuro yawe ya mbere mu Kinyarwanda, izakomeza ikuyobore.",
foot_note: "Umufasha wo kuganira mu Kinyarwanda no mu Cyongereza.",
foot_product: "Porogaramu",
foot_open: "Fungura porogaramu",
foot_contact: "Twandikire",
foot_pron_data: "Amakuru y'imivugire",
foot_credit: "Yubatswe na David 路 Konnie Developing Co",
/* ---------- chat: auth ---------- */
login: "Injira",
signup: "Iyandikishe",
logout: "Sohoka",
profile: "Ikibaho cyawe",
auth_title_login: "Ikaze nanone",
auth_sub_login: "Injira kugira ngo ibiganiro byawe bibikwe.",
auth_title_signup: "Fungura konti",
auth_sub_signup: "Bika ibiganiro byawe ukomereze aho wari ugeze.",
username: "Izina ry'ukoresha",
username_ph: "izinaryawe",
password: "Ijambo ry'ibanga",
or: "cyangwa",
new_here: "Uri mushya?",
have_acct: "Usanzwe ufite konti?",
create_acct: "Fungura konti",
login_instead: "Injira",
err_missing_fields: "Uzuza ibisabwa byombi.",
err_short_username: "Izina ry'ukoresha rigomba kuba nibura inyuguti 3.",
err_short_password: "Ijambo ry'ibanga rigomba kuba nibura inyuguti 6.",
err_taken: "Iryo zina ryarafashwe.",
err_bad_credentials: "Izina cyangwa ijambo ry'ibanga si byo.",
err_rate_limited: "Wagerageje inshuro nyinshi. Tegereza gato.",
acct_created: "Konti yafunguwe. Injira ubu.",
net_err: "Ikibazo cy'umuyoboro. Ongera ugerageze.",
oauth_unconf: "Kwinjira na {p} ntibirashyirwaho. Koresha izina n'ijambo ry'ibanga.",
/* ---------- chat: sidebar + panel ---------- */
new_chat: "Ikiganiro gishya",
search_ph: "Shakisha ibiganiro",
recent: "Ibya vuba",
no_chats: "Nta biganiro bibitse bihari.",
login_hint: "Injira kugira ngo ibiganiro byawe bibikwe.",
panel_sub: "Wiga Ikinyarwanda",
welcome_back: "Ikaze nanone, {name}",
adapt_pill: "Ihuza n'urwego rwawe",
empty_h: "Muraho! Reka tuganire.",
empty_p: "Andika mu Kinyarwanda cyangwa mu Cyongereza. Intyoza ihuza n'urwego rwawe, igukosora buhoro, kandi ikakwigisha uko muganira.",
chip1: "Muraho, ushobora kunyigisha Ikinyarwanda?",
chip2: "Nabwira nte \"thank you very much\" mu Kinyarwanda?",
chip3: "Mbwira inkuru isekeje",
chip4: "Ni iki kiri kuvugwa mu Rwanda uyu munsi?",
msg_ph: "Ohereza ubutumwa bwawe...",
attach: "Ongeraho ifoto",
speak: "Vuga",
send: "Ohereza",
stop: "Hagarika",
remove: "Kuraho",
composer_note: "Intyoza ishobora gukora amakosa 路 Yubatswe na David",
copy: "Koporora",
del: "Siba",
save_phrase: "Bika",
rename: "Hindura izina",
img_big: "Ifoto ni nini cyane (4MB ntarenga).",
mic_blocked: "Mikoro ntiyemewe. Yemere mu igenamiterere rya browser yawe.",
mic_lang: "Iyi browser ntishobora kumva Ikinyarwanda. Gerageza Chrome cyangwa wandike.",
something_wrong: "Hari ikitagenze neza.",
rate_limited: "Wohereje ubutumwa bwinshi cyane. Tegereza gato.",
err_ai_busy: "Intyoza irahuze ubu. Tegereza akanya wongere ugerageze.",
err_ai_timeout: "Intyoza yatinze gusubiza. Ongera ugerageze.",
err_ai_config: "Intyoza ifite ikibazo cya tekiniki. Menyesha ubwubatsi.",
err_ai_error: "Intyoza ntiyashoboye gusubiza. Ongera ugerageze.",
err_bad_image: "Ntibyashobotse gusoma iyo foto. Yongere uyishyiremo.",
err_too_long: "Ubutumwa ni burebure cyane.",
saved_ok: "Byabitswe.",
saved_login: "Injira kugira ngo ubike interuro.",
sources_label: "Inkomoko",
suggest_label: "Ibindi wakwibazaho",
think: [
"Dutegereze gato...",
"Reka mbitekerezeho neza.",
"Hmm, reka nsuzume iki kibazo.",
"Oya, ibi si byo neza. Reka mbisubiremo.",
"Hari uburyo bwiza kurushaho...",
"Ese ibi bihuye n'urwego rwawe?",
"Reka nkugerageze ikindi gitekerezo.",
"Ndimo gushaka amagambo akwiye..."
],
/* ---------- dashboard ---------- */
tab_overview: "Incamake",
tab_saved: "Ibyabitswe",
tab_settings: "Igenamiterere",
change_photo: "Hindura ifoto",
joined: "Wiyandikishije {d}",
st_chats: "Ibiganiro",
st_msgs: "Ubutumwa wohereje",
st_days: "Iminsi wakoze",
st_streak: "Iminsi ikurikirana",
st_saved: "Ibyabitswe",
activity: "Ibyo wakoze mu minsi 7 ishize",
days: ["Cyu", "Mbe", "Kab", "Gat", "Kan", "Gnu", "Gnd"],
saved_empty: "Nta cyabitswe. Kanda ikimenyetso ku butumwa bwa Intyoza kugira ngo ubibike hano.",
set_profile: "Umwirondoro",
set_name: "Izina rigaragara",
set_save: "Bika",
name_saved: "Izina ryabitswe.",
set_appearance: "Isura",
light: "Umucyo",
dark: "Umwijima",
set_lang: "Ururimi rw'urubuga",
lang_rw: "Ikinyarwanda",
lang_en: "English",
set_pw: "Ijambo ry'ibanga",
pw_cur: "Iryo ukoresha ubu",
pw_new: "Irishya (nibura inyuguti 6)",
pw_change: "Hindura ijambo ry'ibanga",
pw_ok: "Ijambo ry'ibanga ryahinduwe.",
set_data: "Ibyawe",
export: "Kuramo ibiganiro byanjye",
clear_chats: "Siba ibiganiro byose",
del_acct: "Siba konti yanjye",
confirm_clear: "Wemeze gusiba ibiganiro BYOSE? Ntibisubirana.",
del_prompt: "Andika DELETE kugira ngo wemeze gusiba konti yawe burundu.",
done: "Rangiza"
},
/* ============================= ENGLISH ============================= */
en: {
theme_title: "Switch theme (light / dark)",
lang_title: "Change language",
nav_features: "Features",
nav_how: "How it works",
nav_pron: "Pronunciation",
nav_contact: "Contact",
open_app: "Open Intyoza",
pill: "Now speaking with amasaku & ubutinde",
h1: "Learn Kinyarwanda.<br>Practise English.<br><em>One real conversation.</em>",
lead: "Intyoza is a patient AI language partner that adapts to your level, corrects you as you speak, and pronounces Kinyarwanda the way it is actually spoken, not the way it is spelled.",
cta_start: "Start a conversation",
cta_see: "See how it works",
meta1_l: "tutor that adapts to you",
meta2_l: "marked words",
meta3_n: "Free",
meta3_l: "to start",
fc1_l: "Pronunciation",
fc2_l: "Level",
fc2_m: "Adapts to you",
fc3_l: "Correction",
fc3_m: "Gentle, in context",
feat_eyebrow: "What you get",
feat_h2: "Built for how people actually pick up a language.",
f1_h: "Conversation first",
f1_p: "No flashcards or drills. You talk, Intyoza replies, and the lesson happens inside the exchange.",
f2_h: "Real pronunciation",
f2_p: "Amasaku and ubutinde marks show true vowel length and stress, so words read the way they are said.",
f3_h: "Corrections that stick",
f3_p: "Mistakes are fixed in the flow of the chat with a short reason, never a red mark or a score.",
f4_h: "Chats that remember",
f4_p: "Every conversation is saved, titled automatically, and waiting where you left it.",
f5_h: "Both directions",
f5_p: "Kinyarwanda speakers sharpening English, English speakers starting Kinyarwanda: same tutor.",
f6_h: "Ready in seconds",
f6_p: "Open it and start talking. Make an account only when you want your history kept.",
how_eyebrow: "A tutor that adapts",
how_h2: "Intyoza changes how it talks to you based on how well you follow.",
s1_tag: "Start",
s1_h: "Begins in Kinyarwanda",
s1_p: "Intyoza speaks only Kinyarwanda from the first message, so you hear the real rhythm and words.",
s2_tag: "When you struggle",
s2_h: "Mixes in a little English",
s2_p: "When it senses you are lost, it adds short English help, then goes back to Kinyarwanda.",
s3_tag: "It adapts",
s3_h: "Follows your level",
s3_p: "If you keep writing in English, Intyoza brings in more Kinyarwanda step by step until you are ready.",
pron_eyebrow: "Amasaku & ubutinde",
pron_h2: "Kinyarwanda spelling hides how words sound.",
pron_p: "Standard writing leaves out vowel length and stress. Intyoza carries a dictionary of marked forms, so it knows that <b>Ababo</b> is held as <b>Aba芒bo</b>, uses that rhythm when it speaks, and shows you the marks when they help.",
pron_btn: "Hear it in a chat",
cta_h: "Muraho. Shall we begin?",
cta_p: "Open Intyoza and say your first sentence in Kinyarwanda. It will take it from there.",
foot_note: "A Kinyarwanda and English conversation companion.",
foot_product: "Product",
foot_open: "Open the app",
foot_contact: "Contact",
foot_pron_data: "Pronunciation data",
foot_credit: "Built by David 路 Konnie Developing Co",
login: "Log in",
signup: "Sign up",
logout: "Log out",
profile: "Your dashboard",
auth_title_login: "Welcome back",
auth_sub_login: "Log in to keep your conversations.",
auth_title_signup: "Create your account",
auth_sub_signup: "Save your chats and pick up where you left off.",
username: "Username",
username_ph: "yourname",
password: "Password",
or: "or",
new_here: "New here?",
have_acct: "Already have an account?",
create_acct: "Create an account",
login_instead: "Log in instead",
err_missing_fields: "Please fill in both fields.",
err_short_username: "Username should be at least 3 characters.",
err_short_password: "Password should be at least 6 characters.",
err_taken: "That username is already taken.",
err_bad_credentials: "Incorrect username or password.",
err_rate_limited: "Too many attempts. Please wait a moment.",
acct_created: "Account created. Log in now.",
net_err: "Network problem. Please try again.",
oauth_unconf: "{p} login isn't configured yet. Use a username and password for now.",
new_chat: "New chat",
search_ph: "Search chats",
recent: "Recent",
no_chats: "No saved chats yet.",
login_hint: "Log in to save your conversations.",
panel_sub: "Practising Kinyarwanda",
welcome_back: "Welcome back, {name}",
adapt_pill: "Adapts to your level",
empty_h: "Muraho! Let's talk.",
empty_p: "Write in Kinyarwanda or English. Intyoza adapts to your level, corrects gently, and teaches as you go.",
chip1: "Hello, can you teach me Kinyarwanda?",
chip2: "How do I say \"thank you very much\"?",
chip3: "Tell me a funny story",
chip4: "What is trending in Rwanda today?",
msg_ph: "Type your message...",
attach: "Attach an image",
speak: "Speak",
send: "Send",
stop: "Stop",
remove: "Remove",
composer_note: "Intyoza can make mistakes 路 Built by David",
copy: "Copy",
del: "Delete",
save_phrase: "Save",
rename: "Rename",
img_big: "Image is too large (4MB max).",
mic_blocked: "Microphone access was blocked. Please allow it in your browser settings.",
mic_lang: "This browser can't recognise Kinyarwanda speech. Try Chrome, or type instead.",
something_wrong: "Something went wrong.",
rate_limited: "You're sending messages too fast. Please wait a moment.",
err_ai_busy: "Intyoza is busy right now. Wait a moment and try again.",
err_ai_timeout: "Intyoza took too long to answer. Please try again.",
err_ai_config: "Intyoza has a technical problem. Please tell the developer.",
err_ai_error: "Intyoza couldn't reply. Please try again.",
err_bad_image: "That image couldn't be read. Please upload it again.",
err_too_long: "That message is too long.",
saved_ok: "Saved.",
saved_login: "Log in to save phrases.",
sources_label: "Sources",
suggest_label: "You could ask next",
think: [
"Just a moment...",
"Let me think this through.",
"Hmm, let me look at this question.",
"Wait, that's not quite right. Let me redo it.",
"Actually, there's a better way...",
"Does this fit your level?",
"Let me try another idea.",
"Looking for the right words..."
],
tab_overview: "Overview",
tab_saved: "Saved",
tab_settings: "Settings",
change_photo: "Change photo",
joined: "Joined {d}",
st_chats: "Chats",
st_msgs: "Messages sent",
st_days: "Active days",
st_streak: "Day streak",
st_saved: "Saved phrases",
activity: "Your last 7 days",
days: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
saved_empty: "Nothing saved yet. Tap the bookmark on any Intyoza message to keep it here.",
set_profile: "Profile",
set_name: "Display name",
set_save: "Save",
name_saved: "Name saved.",
set_appearance: "Appearance",
light: "Light",
dark: "Dark",
set_lang: "Interface language",
lang_rw: "Ikinyarwanda",
lang_en: "English",
set_pw: "Password",
pw_cur: "Current password",
pw_new: "New password (6+ characters)",
pw_change: "Change password",
pw_ok: "Password changed.",
set_data: "Your data",
export: "Download my chats",
clear_chats: "Delete all chats",
del_acct: "Delete my account",
confirm_clear: "Delete ALL your chats? This can't be undone.",
del_prompt: "Type DELETE to permanently delete your account.",
done: "Done"
}
};
/* ---------------- core ---------------- */
const getLang = () => (localStorage.getItem("lang") === "en" ? "en" : "rw");
const getTheme = () => root.dataset.theme === "dark" ? "dark" : "light";
function t(key, vars) {
let v = (I18N[getLang()] || {})[key];
if (v === undefined) v = I18N.rw[key];
if (v === undefined) return key;
if (typeof v === "string" && vars) {
v = v.replace(/\{(\w+)\}/g, (_, n) => (vars[n] !== undefined ? vars[n] : ""));
}
return v;
}
function applyI18n() {
document.querySelectorAll("[data-i18n]").forEach(el => { el.textContent = t(el.dataset.i18n); });
document.querySelectorAll("[data-i18n-html]").forEach(el => { el.innerHTML = t(el.dataset.i18nHtml); });
document.querySelectorAll("[data-i18n-ph]").forEach(el => { el.placeholder = t(el.dataset.i18nPh); });
document.querySelectorAll("[data-i18n-title]").forEach(el => { el.title = t(el.dataset.i18nTitle); });
document.querySelectorAll("[data-lang-label]").forEach(el => { el.textContent = getLang().toUpperCase(); });
}
function emit(fromServer) {
window.dispatchEvent(new CustomEvent("uichange", {
detail: { lang: getLang(), theme: getTheme(), fromServer: !!fromServer }
}));
}
function setLang(lang, fromServer) {
lang = lang === "en" ? "en" : "rw";
try { localStorage.setItem("lang", lang); } catch (e) {}
root.lang = lang;
applyI18n();
emit(fromServer);
}
function setTheme(theme, fromServer) {
theme = theme === "dark" ? "dark" : "light";
try { localStorage.setItem("theme", theme); } catch (e) {}
root.dataset.theme = theme;
emit(fromServer);
}
window.t = t;
window.getLang = getLang;
window.getTheme = getTheme;
window.setLang = setLang;
window.setTheme = setTheme;
window.applyI18n = applyI18n;
/* header buttons (present on both pages) */
const themeBtn = document.getElementById("theme-btn");
const langBtn = document.getElementById("lang-btn");
if (themeBtn) themeBtn.onclick = () => setTheme(getTheme() === "dark" ? "light" : "dark");
if (langBtn) langBtn.onclick = () => setLang(getLang() === "rw" ? "en" : "rw");
root.lang = getLang();
applyI18n();
})();