Source: dashboard/i18n-translations.js

/**
 * @module Intelligence/Internationalization
 * @category Intelligence Platform - Multi-Language Support
 * 
 * @description
 * ## Dashboard i18n Translation Dictionary
 * 
 * Comprehensive translation system for CIA Intelligence Dashboard supporting 14 languages.
 * Provides language-specific translations for UI text, error messages, data labels, and
 * cultural formatting (dates, numbers) using the Intl API.
 * 
 * ### Supported Languages
 * - **Nordic**: English (en), Swedish (sv), Danish (da), Norwegian (no), Finnish (fi)
 * - **European**: German (de), French (fr), Spanish (es), Dutch (nl)
 * - **Middle Eastern**: Arabic (ar), Hebrew (he)
 * - **East Asian**: Japanese (ja), Korean (ko), Chinese Simplified (zh)
 * 
 * ### Translation Categories
 * - **System Messages**: Loading states, errors, retry actions
 * - **Political Terminology**: Party names, risk levels, roles
 * - **UI Labels**: Section headings, metrics, chart labels
 * - **Cultural Formatting**: Date/time formats, number formats
 * 
 * ### Usage Example
 * ```javascript
 * import { t, formatDate, formatNumber } from './i18n-translations.js';
 * 
 * // Simple translation
 * const loadingText = t('loadingData'); // "Loading CIA intelligence data..."
 * 
 * // Nested translation
 * const partyName = t('parties.M'); // "Moderate Party"
 * 
 * // Cultural formatting
 * const formattedDate = formatDate(new Date(), 'sv'); // "13 februari 2026"
 * const formattedNumber = formatNumber(12345.67, 'de'); // "12.345,67"
 * ```
 * 
 * @author Hack23 AB - Intelligence Platforms
 * @license Apache-2.0
 * @version 1.0.0
 * @since 2026-02-13
 */

export const TRANSLATIONS = {
  en: {
    loadingData: 'Loading CIA intelligence data...',
    noDataAvailable: 'No data available',
    noDataDescription: 'Data for this visualization is currently unavailable. Please check back later.',
    errorLoadingData: 'Error loading data. Please try again.',
    errorTitle: 'Something went wrong',
    errorPersists: 'If this problem persists,',
    contactSupport: 'contact support',
    retryButton: 'Retry',
    lastUpdated: 'Last updated',
    parties: {
      M: 'Moderate Party',
      S: 'Social Democrats',
      SD: 'Sweden Democrats',
      C: 'Centre Party',
      V: 'Left Party',
      MP: 'Green Party',
      KD: 'Christian Democrats',
      L: 'Liberals'
    },
    riskLevel: {
      CRITICAL: 'Critical',
      HIGH: 'High',
      MEDIUM: 'Medium',
      LOW: 'Low'
    },
    metrics: {
      seats: 'Seats',
      voteShare: 'Vote Share',
      documents: 'Documents',
      motions: 'Motions',
      attendance: 'Attendance',
      influence: 'Influence'
    }
  },
  sv: {
    loadingData: 'Laddar CIA underrättelsedata...',
    noDataAvailable: 'Ingen data tillgänglig',
    noDataDescription: 'Data för denna visualisering är för närvarande inte tillgänglig. Försök igen senare.',
    errorLoadingData: 'Fel vid inläsning av data. Försök igen.',
    errorTitle: 'Något gick fel',
    errorPersists: 'Om problemet kvarstår,',
    contactSupport: 'kontakta support',
    retryButton: 'Försök igen',
    lastUpdated: 'Senast uppdaterad',
    parties: {
      M: 'Moderaterna',
      S: 'Socialdemokraterna',
      SD: 'Sverigedemokraterna',
      C: 'Centerpartiet',
      V: 'Vänsterpartiet',
      MP: 'Miljöpartiet',
      KD: 'Kristdemokraterna',
      L: 'Liberalerna'
    },
    riskLevel: {
      CRITICAL: 'Kritisk',
      HIGH: 'Hög',
      MEDIUM: 'Medel',
      LOW: 'Låg'
    },
    metrics: {
      seats: 'Mandat',
      voteShare: 'Röstandel',
      documents: 'Dokument',
      motions: 'Motioner',
      attendance: 'Närvaro',
      influence: 'Inflytande'
    }
  },
  da: {
    loadingData: 'Indlæser CIA efterretningsdata...',
    noDataAvailable: 'Ingen tilgængelige data',
    noDataDescription: 'Data til denne visualisering er i øjeblikket ikke tilgængelig. Prøv igen senere.',
    errorLoadingData: 'Fejl ved indlæsning af data. Prøv igen.',
    errorTitle: 'Noget gik galt',
    errorPersists: 'Hvis problemet fortsætter,',
    contactSupport: 'kontakt support',
    retryButton: 'Prøv igen',
    lastUpdated: 'Sidst opdateret',
    parties: {
      M: 'Moderate Parti',
      S: 'Socialdemokraterne',
      SD: 'Sverigedemokraterne',
      C: 'Centerpartiet',
      V: 'Venstrefløjen',
      MP: 'Miljøpartiet',
      KD: 'Kristdemokraterne',
      L: 'Liberalerne'
    },
    riskLevel: {
      CRITICAL: 'Kritisk',
      HIGH: 'Høj',
      MEDIUM: 'Middel',
      LOW: 'Lav'
    },
    metrics: {
      seats: 'Pladser',
      voteShare: 'Stemmeandel',
      documents: 'Dokumenter',
      motions: 'Forslag',
      attendance: 'Fremmøde',
      influence: 'Indflydelse'
    }
  },
  no: {
    loadingData: 'Laster CIA etterretningsdata...',
    noDataAvailable: 'Ingen tilgjengelige data',
    noDataDescription: 'Data for denne visualiseringen er for øyeblikket ikke tilgjengelig. Prøv igjen senere.',
    errorLoadingData: 'Feil ved lasting av data. Prøv igjen.',
    errorTitle: 'Noe gikk galt',
    errorPersists: 'Hvis problemet vedvarer,',
    contactSupport: 'kontakt support',
    retryButton: 'Prøv igjen',
    lastUpdated: 'Sist oppdatert',
    parties: {
      M: 'Moderate Parti',
      S: 'Sosialdemokratene',
      SD: 'Sverigedemokratene',
      C: 'Senterpartiet',
      V: 'Venstrepartiet',
      MP: 'Miljøpartiet',
      KD: 'Kristdemokratene',
      L: 'Liberalene'
    },
    riskLevel: {
      CRITICAL: 'Kritisk',
      HIGH: 'Høy',
      MEDIUM: 'Middels',
      LOW: 'Lav'
    },
    metrics: {
      seats: 'Seter',
      voteShare: 'Stemmeandel',
      documents: 'Dokumenter',
      motions: 'Forslag',
      attendance: 'Oppmøte',
      influence: 'Innflytelse'
    }
  },
  fi: {
    loadingData: 'Ladataan CIA-tiedustelutietoja...',
    noDataAvailable: 'Ei saatavilla olevia tietoja',
    noDataDescription: 'Tämän visualisoinnin tiedot eivät ole tällä hetkellä saatavilla. Yritä myöhemmin uudelleen.',
    errorLoadingData: 'Virhe tietojen latauksessa. Yritä uudelleen.',
    errorTitle: 'Jotain meni pieleen',
    errorPersists: 'Jos ongelma jatkuu,',
    contactSupport: 'ota yhteyttä tukeen',
    retryButton: 'Yritä uudelleen',
    lastUpdated: 'Viimeksi päivitetty',
    parties: {
      M: 'Maltillinen puolue',
      S: 'Sosiaalidemokraatit',
      SD: 'Ruotsidemokraatit',
      C: 'Keskustapuolue',
      V: 'Vasemmistopuolue',
      MP: 'Vihreä puolue',
      KD: 'Kristillisdemokraatit',
      L: 'Liberaalit'
    },
    riskLevel: {
      CRITICAL: 'Kriittinen',
      HIGH: 'Korkea',
      MEDIUM: 'Keskitaso',
      LOW: 'Matala'
    },
    metrics: {
      seats: 'Paikat',
      voteShare: 'Ääniosuus',
      documents: 'Asiakirjat',
      motions: 'Aloitteet',
      attendance: 'Läsnäolo',
      influence: 'Vaikutusvalta'
    }
  },
  de: {
    loadingData: 'CIA-Geheimdienstdaten werden geladen...',
    noDataAvailable: 'Keine Daten verfügbar',
    noDataDescription: 'Daten für diese Visualisierung sind derzeit nicht verfügbar. Bitte versuchen Sie es später erneut.',
    errorLoadingData: 'Fehler beim Laden der Daten. Bitte versuchen Sie es erneut.',
    errorTitle: 'Etwas ist schiefgelaufen',
    errorPersists: 'Wenn das Problem weiterhin besteht,',
    contactSupport: 'Support kontaktieren',
    retryButton: 'Erneut versuchen',
    lastUpdated: 'Zuletzt aktualisiert',
    parties: {
      M: 'Moderate Partei',
      S: 'Sozialdemokraten',
      SD: 'Schwedendemokraten',
      C: 'Zentrumspartei',
      V: 'Linkspartei',
      MP: 'Grüne Partei',
      KD: 'Christdemokraten',
      L: 'Liberale'
    },
    riskLevel: {
      CRITICAL: 'Kritisch',
      HIGH: 'Hoch',
      MEDIUM: 'Mittel',
      LOW: 'Niedrig'
    },
    metrics: {
      seats: 'Sitze',
      voteShare: 'Stimmenanteil',
      documents: 'Dokumente',
      motions: 'Anträge',
      attendance: 'Anwesenheit',
      influence: 'Einfluss'
    }
  },
  fr: {
    loadingData: 'Chargement des données de renseignement CIA...',
    noDataAvailable: 'Aucune donnée disponible',
    noDataDescription: 'Les données pour cette visualisation sont actuellement indisponibles. Veuillez réessayer plus tard.',
    errorLoadingData: 'Erreur lors du chargement des données. Veuillez réessayer.',
    errorTitle: 'Quelque chose s\'est mal passé',
    errorPersists: 'Si ce problème persiste,',
    contactSupport: 'contacter le support',
    retryButton: 'Réessayer',
    lastUpdated: 'Dernière mise à jour',
    parties: {
      M: 'Parti modéré',
      S: 'Sociaux-démocrates',
      SD: 'Démocrates de Suède',
      C: 'Parti du centre',
      V: 'Parti de gauche',
      MP: 'Parti vert',
      KD: 'Chrétiens-démocrates',
      L: 'Libéraux'
    },
    riskLevel: {
      CRITICAL: 'Critique',
      HIGH: 'Élevé',
      MEDIUM: 'Moyen',
      LOW: 'Faible'
    },
    metrics: {
      seats: 'Sièges',
      voteShare: 'Part des voix',
      documents: 'Documents',
      motions: 'Motions',
      attendance: 'Présence',
      influence: 'Influence'
    }
  },
  es: {
    loadingData: 'Cargando datos de inteligencia CIA...',
    noDataAvailable: 'No hay datos disponibles',
    noDataDescription: 'Los datos para esta visualización no están disponibles en este momento. Por favor, inténtelo más tarde.',
    errorLoadingData: 'Error al cargar datos. Por favor, inténtelo de nuevo.',
    errorTitle: 'Algo salió mal',
    errorPersists: 'Si este problema persiste,',
    contactSupport: 'contactar soporte',
    retryButton: 'Reintentar',
    lastUpdated: 'Última actualización',
    parties: {
      M: 'Partido Moderado',
      S: 'Socialdemócratas',
      SD: 'Demócratas de Suecia',
      C: 'Partido de Centro',
      V: 'Partido de Izquierda',
      MP: 'Partido Verde',
      KD: 'Cristianodemócratas',
      L: 'Liberales'
    },
    riskLevel: {
      CRITICAL: 'Crítico',
      HIGH: 'Alto',
      MEDIUM: 'Medio',
      LOW: 'Bajo'
    },
    metrics: {
      seats: 'Escaños',
      voteShare: 'Porcentaje de votos',
      documents: 'Documentos',
      motions: 'Mociones',
      attendance: 'Asistencia',
      influence: 'Influencia'
    }
  },
  nl: {
    loadingData: 'CIA inlichtingengegevens laden...',
    noDataAvailable: 'Geen gegevens beschikbaar',
    noDataDescription: 'Gegevens voor deze visualisatie zijn momenteel niet beschikbaar. Probeer het later opnieuw.',
    errorLoadingData: 'Fout bij het laden van gegevens. Probeer het opnieuw.',
    errorTitle: 'Er ging iets mis',
    errorPersists: 'Als dit probleem aanhoudt,',
    contactSupport: 'neem contact op met ondersteuning',
    retryButton: 'Opnieuw proberen',
    lastUpdated: 'Laatst bijgewerkt',
    parties: {
      M: 'Gematigde Partij',
      S: 'Sociaaldemocraten',
      SD: 'Zweden Democraten',
      C: 'Centrumpartij',
      V: 'Linkse Partij',
      MP: 'Groene Partij',
      KD: 'Christendemocraten',
      L: 'Liberalen'
    },
    riskLevel: {
      CRITICAL: 'Kritiek',
      HIGH: 'Hoog',
      MEDIUM: 'Gemiddeld',
      LOW: 'Laag'
    },
    metrics: {
      seats: 'Zetels',
      voteShare: 'Stemmenpercentage',
      documents: 'Documenten',
      motions: 'Moties',
      attendance: 'Aanwezigheid',
      influence: 'Invloed'
    }
  },
  ar: {
    loadingData: 'جاري تحميل بيانات استخبارات CIA...',
    noDataAvailable: 'لا توجد بيانات متاحة',
    noDataDescription: 'البيانات الخاصة بهذا التصور غير متاحة حالياً. يرجى المحاولة مرة أخرى لاحقاً.',
    errorLoadingData: 'خطأ في تحميل البيانات. يرجى المحاولة مرة أخرى.',
    errorTitle: 'حدث خطأ ما',
    errorPersists: 'إذا استمرت هذه المشكلة،',
    contactSupport: 'اتصل بالدعم',
    retryButton: 'إعادة المحاولة',
    lastUpdated: 'آخر تحديث',
    parties: {
      M: 'الحزب المعتدل',
      S: 'الاشتراكيون الديمقراطيون',
      SD: 'ديمقراطيو السويد',
      C: 'حزب الوسط',
      V: 'حزب اليسار',
      MP: 'الحزب الأخضر',
      KD: 'الديمقراطيون المسيحيون',
      L: 'الليبراليون'
    },
    riskLevel: {
      CRITICAL: 'حرج',
      HIGH: 'عالي',
      MEDIUM: 'متوسط',
      LOW: 'منخفض'
    },
    metrics: {
      seats: 'المقاعد',
      voteShare: 'حصة الأصوات',
      documents: 'الوثائق',
      motions: 'الاقتراحات',
      attendance: 'الحضور',
      influence: 'النفوذ'
    }
  },
  he: {
    loadingData: 'טוען נתוני מודיעין CIA...',
    noDataAvailable: 'אין נתונים זמינים',
    noDataDescription: 'הנתונים עבור המחשה זו אינם זמינים כרגע. אנא נסה שוב מאוחר יותר.',
    errorLoadingData: 'שגיאה בטעינת נתונים. אנא נסה שנית.',
    errorTitle: 'משהו השתבש',
    errorPersists: 'אם הבעיה ממשיכה,',
    contactSupport: 'צור קשר עם התמיכה',
    retryButton: 'נסה שוב',
    lastUpdated: 'עודכן לאחרונה',
    parties: {
      M: 'המפלגה המתונה',
      S: 'הסוציאל-דמוקרטים',
      SD: 'דמוקרטי שבדיה',
      C: 'מפלגת המרכז',
      V: 'מפלגת השמאל',
      MP: 'המפלגה הירוקה',
      KD: 'הנוצרים-דמוקרטים',
      L: 'הליברלים'
    },
    riskLevel: {
      CRITICAL: 'קריטי',
      HIGH: 'גבוה',
      MEDIUM: 'בינוני',
      LOW: 'נמוך'
    },
    metrics: {
      seats: 'מושבים',
      voteShare: 'אחוז קולות',
      documents: 'מסמכים',
      motions: 'הצעות',
      attendance: 'נוכחות',
      influence: 'השפעה'
    }
  },
  ja: {
    loadingData: 'CIA情報データを読み込んでいます...',
    noDataAvailable: '利用可能なデータがありません',
    noDataDescription: 'この視覚化のデータは現在利用できません。後でもう一度お試しください。',
    errorLoadingData: 'データの読み込みエラーです。もう一度お試しください。',
    errorTitle: '問題が発生しました',
    errorPersists: 'この問題が続く場合は、',
    contactSupport: 'サポートに連絡',
    retryButton: '再試行',
    lastUpdated: '最終更新',
    parties: {
      M: '穏健党',
      S: '社会民主党',
      SD: 'スウェーデン民主党',
      C: '中央党',
      V: '左翼党',
      MP: '緑の党',
      KD: 'キリスト教民主党',
      L: '自由党'
    },
    riskLevel: {
      CRITICAL: '重大',
      HIGH: '高',
      MEDIUM: '中',
      LOW: '低'
    },
    metrics: {
      seats: '議席',
      voteShare: '得票率',
      documents: '文書',
      motions: '動議',
      attendance: '出席',
      influence: '影響力'
    }
  },
  ko: {
    loadingData: 'CIA 정보 데이터를 불러오는 중...',
    noDataAvailable: '사용 가능한 데이터가 없습니다',
    noDataDescription: '이 시각화에 대한 데이터는 현재 사용할 수 없습니다. 나중에 다시 확인하십시오.',
    errorLoadingData: '데이터 로드 중 오류가 발생했습니다. 다시 시도해 주세요.',
    errorTitle: '문제가 발생했습니다',
    errorPersists: '이 문제가 지속되면,',
    contactSupport: '지원 팀에 문의',
    retryButton: '다시 시도',
    lastUpdated: '마지막 업데이트',
    parties: {
      M: '온건당',
      S: '사회민주당',
      SD: '스웨덴민주당',
      C: '중앙당',
      V: '좌파당',
      MP: '녹색당',
      KD: '기독교민주당',
      L: '자유당'
    },
    riskLevel: {
      CRITICAL: '심각',
      HIGH: '높음',
      MEDIUM: '보통',
      LOW: '낮음'
    },
    metrics: {
      seats: '의석',
      voteShare: '득표율',
      documents: '문서',
      motions: '동의',
      attendance: '출석',
      influence: '영향력'
    }
  },
  zh: {
    loadingData: '正在加载CIA情报数据...',
    noDataAvailable: '无可用数据',
    noDataDescription: '此可视化的数据目前不可用。请稍后再试。',
    errorLoadingData: '加载数据时出错。请重试。',
    errorTitle: '出现问题',
    errorPersists: '如果此问题持续存在,',
    contactSupport: '联系支持',
    retryButton: '重试',
    lastUpdated: '最后更新',
    parties: {
      M: '温和党',
      S: '社会民主党',
      SD: '瑞典民主党',
      C: '中央党',
      V: '左翼党',
      MP: '绿党',
      KD: '基督教民主党',
      L: '自由党'
    },
    riskLevel: {
      CRITICAL: '严重',
      HIGH: '高',
      MEDIUM: '中',
      LOW: '低'
    },
    metrics: {
      seats: '席位',
      voteShare: '得票份额',
      documents: '文件',
      motions: '动议',
      attendance: '出席',
      influence: '影响力'
    }
  }
};

/**
 * Detect current page language from document.documentElement.lang
 * @returns {string} Language code (en, sv, da, etc.)
 */
export function detectLanguage() {
  const htmlLang = document.documentElement.lang;
  return htmlLang && TRANSLATIONS[htmlLang] ? htmlLang : 'en';
}

/**
 * Get translation for a key
 * @param {string} key - Translation key (supports dot notation like 'parties.M')
 * @param {string} [lang] - Language code (defaults to auto-detected)
 * @returns {string} Translated text
 */
export function t(key, lang = detectLanguage()) {
  const keys = key.split('.');
  let value = TRANSLATIONS[lang] || TRANSLATIONS.en;
  
  for (const k of keys) {
    value = value?.[k];
    if (value === undefined) {
      console.warn(`Translation missing: ${key} for language ${lang}`);
      return key; // Return key as fallback
    }
  }
  
  return value;
}

/**
 * Locale mappings for Intl API
 */
const LOCALE_MAP = {
  en: 'en-US',
  sv: 'sv-SE',
  da: 'da-DK',
  no: 'nb-NO',
  fi: 'fi-FI',
  de: 'de-DE',
  fr: 'fr-FR',
  es: 'es-ES',
  nl: 'nl-NL',
  ar: 'ar-SA',
  he: 'he-IL',
  ja: 'ja-JP',
  ko: 'ko-KR',
  zh: 'zh-CN'
};

/**
 * Format date with cultural awareness
 * @param {Date|string} date - Date to format
 * @param {string} [lang] - Language code
 * @returns {string} Formatted date
 */
export function formatDate(date, lang = detectLanguage()) {
  const locale = LOCALE_MAP[lang] || 'en-US';
  const dateObj = date instanceof Date ? date : new Date(date);
  
  return dateObj.toLocaleDateString(locale, {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
}

/**
 * Format number with cultural awareness
 * @param {number} num - Number to format
 * @param {string} [lang] - Language code
 * @param {Object} [options] - Intl.NumberFormat options
 * @returns {string} Formatted number
 */
export function formatNumber(num, lang = detectLanguage(), options = {}) {
  const locale = LOCALE_MAP[lang] || 'en-US';
  return new Intl.NumberFormat(locale, options).format(num);
}

/**
 * Format percentage with cultural awareness
 * @param {number} num - Number to format as percentage (0-1 range, e.g., 0.5 for 50%)
 * @param {string} [lang] - Language code
 * @returns {string} Formatted percentage
 */
export function formatPercentage(num, lang = detectLanguage()) {
  return formatNumber(num, lang, {
    style: 'percent',
    minimumFractionDigits: 1,
    maximumFractionDigits: 1
  });
}

/**
 * Format currency (SEK) with cultural awareness
 * @param {number} amount - Amount to format
 * @param {string} [lang] - Language code
 * @returns {string} Formatted currency
 */
export function formatCurrency(amount, lang = detectLanguage()) {
  const locale = LOCALE_MAP[lang] || 'en-US';
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency: 'SEK'
  }).format(amount);
}