diff --git a/app/templates/base.html b/app/templates/base.html index 97028ab..9bbb46f 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -154,6 +154,40 @@ try { localStorage.setItem('cassandra.theme', newTheme); } catch (e) {} }; + // Static-label i18n dictionary. AI-generated content is re-fetched via + // HTMX (server-side translation), but plain UI labels are baked into + // the HTML at render time. This dict + applyI18n() below let the + // language toggle swap labels live without a page refresh. + // Convention: … (sets textContent), + // (sets .placeholder). + // First-render correctness is handled by the template's + // {% if user_lang == 'it' %} block — applyI18n only kicks in on + // subsequent toggle events. + window.CASSANDRA_I18N = { + 'chat.title': { en: 'Ask Cassandra', + it: 'Chiedi a Cassandra' }, + 'chat.hint': { en: 'grounded on the latest log + live data', + it: "basato sull'ultimo log + dati in tempo reale" }, + 'chat.lede': { en: "Ask about today's analysis. The model sees the latest strategic log, live market readings across all groups, and the last 24h of thesis-filtered headlines. Refresh wipes this conversation.", + it: "Fai domande sull'analisi di oggi. Il modello vede l'ultimo log strategico, le quotazioni di mercato in tempo reale per tutti i gruppi e le ultime 24h di titoli filtrati per tesi. Un refresh della pagina cancella questa conversazione." }, + 'chat.placeholder': { en: 'e.g. why is the defence sleeve flat through Hormuz?', + it: 'es. perché il comparto difesa è piatto nonostante Hormuz?' }, + 'chat.send': { en: 'Send', + it: 'Invia' }, + }; + window.cassandraApplyI18n = function (lang) { + document.querySelectorAll('[data-i18n]').forEach(function (el) { + var key = el.getAttribute('data-i18n'); + var entry = window.CASSANDRA_I18N[key]; + if (entry && entry[lang] != null) el.textContent = entry[lang]; + }); + document.querySelectorAll('[data-i18n-placeholder]').forEach(function (el) { + var key = el.getAttribute('data-i18n-placeholder'); + var entry = window.CASSANDRA_I18N[key]; + if (entry && entry[lang] != null) el.placeholder = entry[lang]; + }); + }; + window.cassandraSetLang = async function (newLang) { var pill = document.getElementById('lang-toggle'); if (!pill) return; @@ -170,6 +204,8 @@ body: JSON.stringify({lang: newLang}), }); if (!r.ok) throw new Error('HTTP ' + r.status); + // Swap any static UI labels that have i18n bindings. + window.cassandraApplyI18n(newLang); // Trigger HTMX-driven panels to re-fetch in the new language. // Same shape as cassandraSetTone — every panel that listens to // tone-changed also listens to lang-changed. diff --git a/app/templates/log.html b/app/templates/log.html index 8370050..cadc3f1 100644 --- a/app/templates/log.html +++ b/app/templates/log.html @@ -33,28 +33,18 @@ {% if paid %} {% else %}