// Internationalization — window.t, window.setLang, window.useLang
const TRANSLATIONS = {
  en: {
    nav_workspace: 'Workspace', nav_account: 'Account',
    nav_home: 'Home', nav_transactions: 'Transactions',
    nav_recurring: 'Recurring', nav_report: 'Report', nav_settings: 'Settings',
    save: 'Save', cancel: 'Cancel', delete: 'Delete', add: 'Add', loading: 'Loading…',
    saving: 'Saving…', saved: 'Saved!', optional: 'Optional',
    amount: 'Amount', note: 'Note', date: 'Date', search_ph: 'Search…',
    expense: 'Expense', income: 'Income', net: 'Net', all: 'All',
    monthly: 'Monthly', yearly: 'Yearly', frequency: 'Frequency',
    today: 'Today', yesterday: 'Yesterday', tomorrow: 'Tomorrow',
    in_days: 'In {n}d', days_ago: '{n}d ago', pick_date: 'Pick date',
    period_day: 'Day', period_week: 'Week', period_month: 'Month',
    period_year: 'Year', period_overall: 'Overall', all_time: 'All time', last_7_days: 'Last 7 days',
    what_for: 'What for?', what_from: 'What from?',
    new_txn: 'New transaction', edit_txn: 'Edit transaction',
    no_txns_found: 'No transactions found.', entry: 'entry', entries: 'entries',
    save_txn: 'Save transaction', grade_this_month: '· Grade {grade} this month',
    welcome_back: 'Welcome back', todays_net: "Today's net",
    this_month: 'This month', savings_rate: 'Savings rate', grade: 'Grade',
    total_expenses: 'total expenses', recent_activity: 'Recent activity',
    view_all: 'View all', no_txns_yet: 'No transactions yet.',
    recurring_sub: 'Subscriptions, bills, and regular income',
    new_recurring: 'New recurring', new_recurring_title: 'New recurring', edit_recurring_title: 'Edit recurring',
    monthly_out: 'Monthly outgoing', monthly_in: 'Monthly incoming',
    net_per_month: 'Net per month', after_fixed: 'After fixed expenses',
    active: 'active', sorted_by_due: 'sorted by next due',
    next_due: 'Next due', due_today: 'Due today', no_recurring: 'No recurring items yet.',
    confirm_btn: 'Confirm',
    financial_report: 'Financial Report', where_money: 'Where your money is going',
    financial_grade: 'Financial grade', mo6_trend: '6-month trend',
    income_vs_exp: 'Income vs expenses', by_category: 'Spending by category',
    insights: 'Insights', auto_generated: 'Auto-generated',
    no_expenses: 'No expenses for this period.',
    add_for_insights: 'Add transactions to see insights.',
    saving_pct: "You're saving {pct}% of income this period.",
    no_income_recorded: 'No income recorded for this period.',
    spent: 'SPENT', week: 'Week', month: 'Month', year: 'Year',
    insight_sr_label: 'Savings rate', insight_top_exp: 'Top expense', insight_net: 'Net this period',
    settings_title: 'Settings', settings_sub: 'Manage preferences and your data',
    s_account: 'Account', s_account_desc: 'Your profile and regional preferences.',
    s_appearance: 'Appearance', s_appearance_desc: 'How Odemes looks on this device.',
    s_data: 'Data', s_data_desc: 'Backup, export, and clear your transaction history.',
    s_security: 'Security', s_security_desc: 'How you sign in to Odemes.',
    currency: 'Currency', currency_sub: "Used for new transactions. Existing data isn't converted.",
    language: 'Language', language_sub: 'Display language across the app.',
    week_starts: 'Week starts on', sunday: 'Sunday', monday: 'Monday',
    theme: 'Theme', theme_sub: 'Light or dark across the app.',
    light: 'Light', dark: 'Dark',
    accent: 'Accent color', accent_sub: 'Tints buttons, links, and highlights.',
    export_csv: 'Export as CSV', export_csv_sub: 'Download a spreadsheet of all transactions.',
    export_btn: 'Export',
    cloud_backup: 'Cloud backup', cloud_backup_sub: 'Auto-sync to your account.',
    delete_data: 'Delete all data', delete_data_sub: 'Removes every transaction and recurring item. Cannot be undone.',
    sign_out: 'Sign out', sign_out_sub: 'Revokes this session.',
    email_label: 'Email', sign_method: 'Sign-in method',
    delete_confirm_title: 'Delete all data?',
    delete_confirm_body: 'This will permanently remove all transactions and recurring items. This action cannot be undone.',
    delete_confirm_btn: 'Yes, delete everything',
    version_label: 'Odemes Web · v1.0.0', build_label: 'build 2026.05.14',
    auth_welcome: 'Welcome to Odemes', auth_sub: 'Sign in to continue to your dashboard.',
    continue_google: 'Continue with Google', continue_apple: 'Continue with Apple',
    soon: 'Soon', ssl_badge: 'SSL · 256-bit · SOC 2 Type II', privacy_terms: 'Privacy & Terms',
    auth_eyebrow: 'Personal finance, in plain sight',
    auth_headline_1: 'Two taps a day.', auth_headline_2: 'One honest grade.',
    auth_lede: 'Log income and expenses in seconds. Odemes scores your month from A to F so you always know where you stand — without spreadsheets, categories, or guilt.',
    auth_trusted: 'Trusted by 42,000 mindful spenders', connecting: 'Connecting…',
    on_track: "You're on track", saved_pct_target: 'Saved {pct}% of target · {days} days ahead',
    mobile_app_title: 'Get the Odemes app', mobile_app_sub: 'Track money faster on iPhone',
    mobile_app_get: 'Get',
  },
  es: {
    nav_workspace: 'Espacio', nav_account: 'Cuenta',
    nav_home: 'Inicio', nav_transactions: 'Transacciones',
    nav_recurring: 'Recurrentes', nav_report: 'Informe', nav_settings: 'Ajustes',
    save: 'Guardar', cancel: 'Cancelar', delete: 'Eliminar', add: 'Añadir', loading: 'Cargando…',
    saving: 'Guardando…', saved: '¡Guardado!', optional: 'Opcional',
    amount: 'Importe', note: 'Nota', date: 'Fecha', search_ph: 'Buscar…',
    expense: 'Gasto', income: 'Ingreso', net: 'Neto', all: 'Todos',
    monthly: 'Mensual', yearly: 'Anual', frequency: 'Frecuencia',
    today: 'Hoy', yesterday: 'Ayer', tomorrow: 'Mañana',
    in_days: 'En {n}d', days_ago: 'Hace {n}d', pick_date: 'Elegir fecha',
    period_day: 'Día', period_week: 'Semana', period_month: 'Mes',
    period_year: 'Año', period_overall: 'General', all_time: 'Todo el tiempo', last_7_days: 'Últimos 7 días',
    what_for: '¿Para qué?', what_from: '¿De dónde?',
    new_txn: 'Nueva transacción', edit_txn: 'Editar transacción',
    no_txns_found: 'Sin transacciones.', entry: 'entrada', entries: 'entradas',
    save_txn: 'Guardar transacción', grade_this_month: '· Nota {grade} este mes',
    welcome_back: 'Bienvenido', todays_net: 'Neto hoy',
    this_month: 'Este mes', savings_rate: 'Tasa de ahorro', grade: 'Nota',
    total_expenses: 'gastos totales', recent_activity: 'Actividad reciente',
    view_all: 'Ver todo', no_txns_yet: 'Sin transacciones.',
    recurring_sub: 'Suscripciones, facturas e ingresos regulares',
    new_recurring: 'Nuevo recurrente', new_recurring_title: 'Nuevo recurrente', edit_recurring_title: 'Editar recurrente',
    monthly_out: 'Gastos mensuales', monthly_in: 'Ingresos mensuales',
    net_per_month: 'Neto mensual', after_fixed: 'Tras gastos fijos',
    active: 'activos', sorted_by_due: 'por próximo vencimiento',
    next_due: 'Próximo vencimiento', due_today: 'Vence hoy', no_recurring: 'Sin recurrentes.',
    confirm_btn: 'Confirmar',
    financial_report: 'Informe Financiero', where_money: 'Dónde va tu dinero',
    financial_grade: 'Calificación financiera', mo6_trend: 'Tendencia 6 meses',
    income_vs_exp: 'Ingresos vs gastos', by_category: 'Gastos por categoría',
    insights: 'Perspectivas', auto_generated: 'Auto-generado',
    no_expenses: 'Sin gastos en este período.',
    add_for_insights: 'Añade transacciones para ver perspectivas.',
    saving_pct: 'Ahorrando {pct}% de ingresos este período.',
    no_income_recorded: 'Sin ingresos registrados en este período.',
    spent: 'GASTO', week: 'Semana', month: 'Mes', year: 'Año',
    insight_sr_label: 'Tasa de ahorro', insight_top_exp: 'Gasto principal', insight_net: 'Neto este período',
    settings_title: 'Ajustes', settings_sub: 'Gestiona preferencias y tus datos',
    s_account: 'Cuenta', s_account_desc: 'Tu perfil y preferencias regionales.',
    s_appearance: 'Apariencia', s_appearance_desc: 'Cómo se ve Odemes en este dispositivo.',
    s_data: 'Datos', s_data_desc: 'Copia de seguridad, exportar y limpiar historial.',
    s_security: 'Seguridad', s_security_desc: 'Cómo inicias sesión en Odemes.',
    currency: 'Moneda', currency_sub: 'Usada para nuevas transacciones. Los datos existentes no se convierten.',
    language: 'Idioma', language_sub: 'Idioma en toda la app.',
    week_starts: 'La semana empieza el', sunday: 'Domingo', monday: 'Lunes',
    theme: 'Tema', theme_sub: 'Claro u oscuro en toda la app.',
    light: 'Claro', dark: 'Oscuro',
    accent: 'Color de acento', accent_sub: 'Tinte en botones, enlaces y resaltados.',
    export_csv: 'Exportar como CSV', export_csv_sub: 'Descargar hoja de cálculo de todas las transacciones.',
    export_btn: 'Exportar',
    cloud_backup: 'Copia en la nube', cloud_backup_sub: 'Sincronización automática con tu cuenta.',
    delete_data: 'Eliminar todos los datos', delete_data_sub: 'Elimina todas las transacciones y recurrentes. No se puede deshacer.',
    sign_out: 'Cerrar sesión', sign_out_sub: 'Revoca esta sesión.',
    email_label: 'Correo', sign_method: 'Método de acceso',
    delete_confirm_title: '¿Eliminar todos los datos?',
    delete_confirm_body: 'Esto eliminará permanentemente todas las transacciones y recurrentes. Esta acción no se puede deshacer.',
    delete_confirm_btn: 'Sí, eliminar todo',
    version_label: 'Odemes Web · v1.0.0', build_label: 'compilación 2026.05.14',
    auth_welcome: 'Bienvenido a Odemes', auth_sub: 'Inicia sesión para continuar.',
    continue_google: 'Continuar con Google', continue_apple: 'Continuar con Apple',
    soon: 'Pronto', ssl_badge: 'SSL · 256-bit · SOC 2 Tipo II', privacy_terms: 'Privacidad y Términos',
    auth_eyebrow: 'Finanzas personales, a la vista',
    auth_headline_1: 'Dos toques al día.', auth_headline_2: 'Una nota honesta.',
    auth_lede: 'Registra ingresos y gastos en segundos. Odemes puntúa tu mes de A a F para que siempre sepas dónde estás — sin hojas de cálculo, categorías ni culpa.',
    auth_trusted: 'Elegido por 42.000 ahorradores', connecting: 'Conectando…',
    on_track: 'Vas bien', saved_pct_target: 'Ahorro del {pct}% · {days} días por delante',
    mobile_app_title: 'Descarga Odemes', mobile_app_sub: 'Controla tu dinero más rápido en iPhone',
    mobile_app_get: 'Obtener',
  },
  pt: {
    nav_workspace: 'Área de Trabalho', nav_account: 'Conta',
    nav_home: 'Início', nav_transactions: 'Transações',
    nav_recurring: 'Recorrentes', nav_report: 'Relatório', nav_settings: 'Configurações',
    save: 'Guardar', cancel: 'Cancelar', delete: 'Eliminar', add: 'Adicionar', loading: 'A carregar…',
    saving: 'A guardar…', saved: 'Guardado!', optional: 'Opcional',
    amount: 'Valor', note: 'Nota', date: 'Data', search_ph: 'Pesquisar…',
    expense: 'Despesa', income: 'Receita', net: 'Líquido', all: 'Todos',
    monthly: 'Mensal', yearly: 'Anual', frequency: 'Frequência',
    today: 'Hoje', yesterday: 'Ontem', tomorrow: 'Amanhã',
    in_days: 'Em {n}d', days_ago: 'Há {n}d', pick_date: 'Escolher data',
    period_day: 'Dia', period_week: 'Semana', period_month: 'Mês',
    period_year: 'Ano', period_overall: 'Geral', all_time: 'Todo o tempo', last_7_days: 'Últimos 7 dias',
    what_for: 'Para quê?', what_from: 'De onde?',
    new_txn: 'Nova transação', edit_txn: 'Editar transação',
    no_txns_found: 'Sem transações.', entry: 'entrada', entries: 'entradas',
    save_txn: 'Guardar transação', grade_this_month: '· Nota {grade} este mês',
    welcome_back: 'Bem-vindo', todays_net: 'Líquido hoje',
    this_month: 'Este mês', savings_rate: 'Taxa de poupança', grade: 'Nota',
    total_expenses: 'total de despesas', recent_activity: 'Atividade recente',
    view_all: 'Ver tudo', no_txns_yet: 'Sem transações.',
    recurring_sub: 'Subscrições, faturas e receitas regulares',
    new_recurring: 'Nova recorrente', new_recurring_title: 'Nova recorrente', edit_recurring_title: 'Editar recorrente',
    monthly_out: 'Saídas mensais', monthly_in: 'Entradas mensais',
    net_per_month: 'Líquido mensal', after_fixed: 'Após despesas fixas',
    active: 'ativas', sorted_by_due: 'por próximo vencimento',
    next_due: 'Próximo vencimento', due_today: 'Vence hoje', no_recurring: 'Sem recorrentes.',
    confirm_btn: 'Confirmar',
    financial_report: 'Relatório Financeiro', where_money: 'Para onde vai o seu dinheiro',
    financial_grade: 'Nota financeira', mo6_trend: 'Tendência 6 meses',
    income_vs_exp: 'Receitas vs despesas', by_category: 'Despesas por categoria',
    insights: 'Perspetivas', auto_generated: 'Auto-gerado',
    no_expenses: 'Sem despesas neste período.',
    add_for_insights: 'Adicione transações para ver perspetivas.',
    saving_pct: 'Está a poupar {pct}% das receitas neste período.',
    no_income_recorded: 'Sem receitas registadas neste período.',
    spent: 'GASTO', week: 'Semana', month: 'Mês', year: 'Ano',
    insight_sr_label: 'Taxa de poupança', insight_top_exp: 'Principal despesa', insight_net: 'Líquido neste período',
    settings_title: 'Configurações', settings_sub: 'Gerir preferências e os seus dados',
    s_account: 'Conta', s_account_desc: 'O seu perfil e preferências regionais.',
    s_appearance: 'Aparência', s_appearance_desc: 'Como o Odemes aparece neste dispositivo.',
    s_data: 'Dados', s_data_desc: 'Cópia de segurança, exportar e limpar histórico.',
    s_security: 'Segurança', s_security_desc: 'Como inicia sessão no Odemes.',
    currency: 'Moeda', currency_sub: 'Usada para novas transações. Os dados existentes não são convertidos.',
    language: 'Idioma', language_sub: 'Idioma em toda a app.',
    week_starts: 'A semana começa em', sunday: 'Domingo', monday: 'Segunda-feira',
    theme: 'Tema', theme_sub: 'Claro ou escuro em toda a app.',
    light: 'Claro', dark: 'Escuro',
    accent: 'Cor de destaque', accent_sub: 'Tonalidade em botões, links e destaques.',
    export_csv: 'Exportar como CSV', export_csv_sub: 'Descarregar folha de cálculo com todas as transações.',
    export_btn: 'Exportar',
    cloud_backup: 'Cópia na nuvem', cloud_backup_sub: 'Sincronização automática com a sua conta.',
    delete_data: 'Eliminar todos os dados', delete_data_sub: 'Remove todas as transações e recorrentes. Não pode ser desfeito.',
    sign_out: 'Terminar sessão', sign_out_sub: 'Revoga esta sessão.',
    email_label: 'Email', sign_method: 'Método de acesso',
    delete_confirm_title: 'Eliminar todos os dados?',
    delete_confirm_body: 'Isto irá remover permanentemente todas as transações e recorrentes. Esta ação não pode ser desfeita.',
    delete_confirm_btn: 'Sim, eliminar tudo',
    version_label: 'Odemes Web · v1.0.0', build_label: 'build 2026.05.14',
    auth_welcome: 'Bem-vindo ao Odemes', auth_sub: 'Inicie sessão para continuar.',
    continue_google: 'Continuar com Google', continue_apple: 'Continuar com Apple',
    soon: 'Brevemente', ssl_badge: 'SSL · 256-bit · SOC 2 Tipo II', privacy_terms: 'Privacidade & Termos',
    auth_eyebrow: 'Finanças pessoais, à vista',
    auth_headline_1: 'Dois toques por dia.', auth_headline_2: 'Uma nota honesta.',
    auth_lede: 'Registe receitas e despesas em segundos. O Odemes classifica o seu mês de A a F para que saiba sempre onde está — sem folhas de cálculo, categorias ou culpa.',
    auth_trusted: 'Confiado por 42.000 poupadores', connecting: 'A ligar…',
    on_track: 'No bom caminho', saved_pct_target: 'Poupança de {pct}% · {days} dias adiantado',
    mobile_app_title: 'Baixe o Odemes', mobile_app_sub: 'Controle seu dinheiro mais rápido no iPhone',
    mobile_app_get: 'Baixar',
  },
  fr: {
    nav_workspace: 'Espace', nav_account: 'Compte',
    nav_home: 'Accueil', nav_transactions: 'Transactions',
    nav_recurring: 'Récurrents', nav_report: 'Rapport', nav_settings: 'Paramètres',
    save: 'Enregistrer', cancel: 'Annuler', delete: 'Supprimer', add: 'Ajouter', loading: 'Chargement…',
    saving: 'Enregistrement…', saved: 'Enregistré !', optional: 'Optionnel',
    amount: 'Montant', note: 'Note', date: 'Date', search_ph: 'Rechercher…',
    expense: 'Dépense', income: 'Revenu', net: 'Net', all: 'Tout',
    monthly: 'Mensuel', yearly: 'Annuel', frequency: 'Fréquence',
    today: "Aujourd'hui", yesterday: 'Hier', tomorrow: 'Demain',
    in_days: 'Dans {n}j', days_ago: 'Il y a {n}j', pick_date: 'Choisir une date',
    period_day: 'Jour', period_week: 'Semaine', period_month: 'Mois',
    period_year: 'Année', period_overall: 'Global', all_time: 'Tout le temps', last_7_days: '7 derniers jours',
    what_for: 'Pour quoi ?', what_from: 'De quoi ?',
    new_txn: 'Nouvelle transaction', edit_txn: 'Modifier la transaction',
    no_txns_found: 'Aucune transaction.', entry: 'entrée', entries: 'entrées',
    save_txn: 'Enregistrer la transaction', grade_this_month: '· Note {grade} ce mois',
    welcome_back: 'Bon retour', todays_net: "Net aujourd'hui",
    this_month: 'Ce mois', savings_rate: "Taux d'épargne", grade: 'Note',
    total_expenses: 'dépenses totales', recent_activity: 'Activité récente',
    view_all: 'Voir tout', no_txns_yet: 'Aucune transaction.',
    recurring_sub: 'Abonnements, factures et revenus réguliers',
    new_recurring: 'Nouveau récurrent', new_recurring_title: 'Nouveau récurrent', edit_recurring_title: 'Modifier le récurrent',
    monthly_out: 'Sorties mensuelles', monthly_in: 'Entrées mensuelles',
    net_per_month: 'Net mensuel', after_fixed: 'Après charges fixes',
    active: 'actifs', sorted_by_due: 'par prochaine échéance',
    next_due: 'Prochaine échéance', due_today: "Dû aujourd'hui", no_recurring: 'Aucun récurrent.',
    confirm_btn: 'Confirmer',
    financial_report: 'Rapport Financier', where_money: 'Où va votre argent',
    financial_grade: 'Note financière', mo6_trend: 'Tendance 6 mois',
    income_vs_exp: 'Revenus vs dépenses', by_category: 'Dépenses par catégorie',
    insights: 'Aperçus', auto_generated: 'Auto-généré',
    no_expenses: 'Aucune dépense pour cette période.',
    add_for_insights: 'Ajoutez des transactions pour voir les aperçus.',
    saving_pct: 'Vous épargnez {pct}% de vos revenus cette période.',
    no_income_recorded: 'Aucun revenu enregistré pour cette période.',
    spent: 'DÉPENSÉ', week: 'Semaine', month: 'Mois', year: 'Année',
    insight_sr_label: "Taux d'épargne", insight_top_exp: 'Dépense principale', insight_net: 'Net cette période',
    settings_title: 'Paramètres', settings_sub: 'Gérer les préférences et vos données',
    s_account: 'Compte', s_account_desc: 'Votre profil et préférences régionales.',
    s_appearance: 'Apparence', s_appearance_desc: "Apparence d'Odemes sur cet appareil.",
    s_data: 'Données', s_data_desc: 'Sauvegarde, export et nettoyage de vos transactions.',
    s_security: 'Sécurité', s_security_desc: 'Comment vous vous connectez à Odemes.',
    currency: 'Devise', currency_sub: 'Utilisée pour les nouvelles transactions. Les données existantes ne sont pas converties.',
    language: 'Langue', language_sub: "Langue dans toute l'application.",
    week_starts: 'La semaine commence le', sunday: 'Dimanche', monday: 'Lundi',
    theme: 'Thème', theme_sub: "Clair ou sombre dans toute l'application.",
    light: 'Clair', dark: 'Sombre',
    accent: "Couleur d'accentuation", accent_sub: 'Teinte les boutons, liens et surlignages.',
    export_csv: 'Exporter en CSV', export_csv_sub: 'Télécharger un tableur de toutes les transactions.',
    export_btn: 'Exporter',
    cloud_backup: 'Sauvegarde cloud', cloud_backup_sub: 'Synchronisation automatique avec votre compte.',
    delete_data: 'Supprimer toutes les données', delete_data_sub: 'Supprime toutes les transactions et récurrents. Irréversible.',
    sign_out: 'Se déconnecter', sign_out_sub: 'Révoque cette session.',
    email_label: 'Email', sign_method: 'Méthode de connexion',
    delete_confirm_title: 'Supprimer toutes les données ?',
    delete_confirm_body: 'Ceci supprimera définitivement toutes les transactions et récurrents. Cette action est irréversible.',
    delete_confirm_btn: 'Oui, tout supprimer',
    version_label: 'Odemes Web · v1.0.0', build_label: 'build 2026.05.14',
    auth_welcome: 'Bienvenue sur Odemes', auth_sub: 'Connectez-vous pour continuer.',
    continue_google: 'Continuer avec Google', continue_apple: 'Continuer avec Apple',
    soon: 'Bientôt', ssl_badge: 'SSL · 256-bit · SOC 2 Type II', privacy_terms: 'Confidentialité & CGU',
    auth_eyebrow: 'Finances personnelles, en clair',
    auth_headline_1: 'Deux clics par jour.', auth_headline_2: 'Une note honnête.',
    auth_lede: "Enregistrez revenus et dépenses en quelques secondes. Odemes note votre mois de A à F pour que vous sachiez toujours où vous en êtes — sans tableurs, catégories ni culpabilité.",
    auth_trusted: 'Approuvé par 42 000 épargnants', connecting: 'Connexion…',
    on_track: 'Vous êtes sur la bonne voie', saved_pct_target: 'Épargné {pct}% · {days} jours en avance',
    mobile_app_title: "Téléchargez Odemes", mobile_app_sub: 'Suivez votre argent plus vite sur iPhone',
    mobile_app_get: 'Obtenir',
  },
};

const LOCALE_MAP = { en: 'en-US', es: 'es-ES', pt: 'pt-PT', fr: 'fr-FR' };

let _storedLang;
try { _storedLang = localStorage.getItem('odemes-lang'); } catch(e) {}
window._lang = (_storedLang && TRANSLATIONS[_storedLang]) ? _storedLang : 'en';
window._i18nLocale = LOCALE_MAP[window._lang] || 'en-US';

window.t = function(key, params) {
  const tr = TRANSLATIONS[window._lang] || TRANSLATIONS.en;
  let str = tr[key] !== undefined ? tr[key] : (TRANSLATIONS.en[key] !== undefined ? TRANSLATIONS.en[key] : key);
  if (params) {
    Object.entries(params).forEach(([k, v]) => {
      str = str.replace(new RegExp('\\{' + k + '\\}', 'g'), v);
    });
  }
  return str;
};

window.setLang = function(lang) {
  if (!lang || !TRANSLATIONS[lang] || lang === window._lang) return;
  window._lang = lang;
  window._i18nLocale = LOCALE_MAP[lang] || 'en-US';
  try { localStorage.setItem('odemes-lang', lang); } catch(e) {}
  window.dispatchEvent(new CustomEvent('odemes-lang-change', { detail: lang }));
};

window.useLang = function() {
  const [, forceUpdate] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    const handler = () => forceUpdate();
    window.addEventListener('odemes-lang-change', handler);
    return () => window.removeEventListener('odemes-lang-change', handler);
  }, []);
  return window._lang;
};
