From 5643050eb6d3907ef2309ea6682168e127141e18 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Sun, 26 Oct 2025 13:20:56 +1300 Subject: [PATCH] fix(i18n): complete architecture page translations and fix diagram modals - Added data-i18n to service card descriptions (validator, pressure, metacognitive, deliberation) - Fixed interactive-diagram.js to properly load translations from i18n system - Added language change handlers for dynamic modal updates - All service cards and modals now fully translate across EN/DE/FR --- public/architecture.html | 8 +- public/js/components/interactive-diagram.js | 156 ++++++++++++++------ 2 files changed, 114 insertions(+), 50 deletions(-) diff --git a/public/architecture.html b/public/architecture.html index 704eba2a..c021c345 100644 --- a/public/architecture.html +++ b/public/architecture.html @@ -251,7 +251,7 @@

- Validates AI actions against instruction history. Aims to prevent pattern bias overriding explicit directives. +

Early Promise: Independent verification—AI claims checked against external source. @@ -268,7 +268,7 @@

- Monitors AI performance degradation. Escalates when context pressure threatens quality. +

Early Promise: Objective metrics may detect manipulation attempts early. @@ -285,7 +285,7 @@

- Requires AI to pause and verify complex operations before execution. Structural safety check. +

Early Promise: Architectural gates aim to enforce verification steps. @@ -302,7 +302,7 @@

- Facilitates multi-stakeholder deliberation for values conflicts. AI provides facilitation, not authority. +

Early Promise: Human judgment required—architecturally enforced escalation for values. diff --git a/public/js/components/interactive-diagram.js b/public/js/components/interactive-diagram.js index 8261b703..7356d483 100644 --- a/public/js/components/interactive-diagram.js +++ b/public/js/components/interactive-diagram.js @@ -57,6 +57,116 @@ class InteractiveDiagram { console.log('[InteractiveDiagram] Loaded translations for', Object.keys(this.serviceData).length, 'services'); } + handleLanguageChange() { + console.log('[InteractiveDiagram] Language changed, reloading translations'); + this.loadTranslations(); + // Re-render current service if one is active + if (this.activeService) { + const service = this.serviceData[this.activeService]; + if (service) { + this.renderServicePanel(service); + } + } + } + + init() { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => this.setup()); + } else { + this.setup(); + } + + console.log('[InteractiveDiagram] Initialized'); + } + + setup() { + // SVG is loaded via tag, need to access its contentDocument + const objectElement = document.getElementById('interactive-svg-object'); + if (!objectElement) { + console.warn('[InteractiveDiagram] SVG object element not found'); + return; + } + + // Wait for object to load with retry mechanism + const initializeSVG = () => { + const svgDoc = objectElement.contentDocument; + if (!svgDoc) { + console.warn('[InteractiveDiagram] Could not access SVG contentDocument, retrying...'); + setTimeout(initializeSVG, 100); + return; + } + + // The SVG is the document element itself, or we can query for it + let svg = svgDoc.getElementById('interactive-arch-diagram'); + if (!svg) { + // Try getting the root SVG element + svg = svgDoc.documentElement; + console.log('[InteractiveDiagram] Using documentElement as SVG'); + } + + if (!svg) { + console.warn('[InteractiveDiagram] SVG diagram not found in contentDocument'); + return; + } + + // Verify it's actually an SVG element (case-insensitive check) + const tagName = svg.tagName ? svg.tagName.toLowerCase() : ''; + if (tagName !== 'svg') { + console.warn('[InteractiveDiagram] Element found but not SVG, tagName:', tagName, '- retrying...'); + // This is the race condition - contentDocument is HTML, not SVG yet + setTimeout(initializeSVG, 100); + return; + } + + // Store reference to SVG document for later use + this.svgDoc = svgDoc; + this.svg = svg; + + const nodes = svg.querySelectorAll('.service-node'); + console.log(`[InteractiveDiagram] Found ${nodes.length} service nodes`); + + if (nodes.length === 0) { + console.warn('[InteractiveDiagram] No service nodes found in SVG'); + return; + } + + nodes.forEach(node => { + const serviceId = node.getAttribute('data-service'); + + // Click handler + node.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + this.showServiceDetails(serviceId); + }, true); + + // Touch support for mobile devices + node.addEventListener('touchstart', (e) => { + e.preventDefault(); + const serviceId = node.getAttribute('data-service'); + this.showServiceDetails(serviceId); + }, { passive: false }); + + // Hover effects + node.addEventListener('mouseenter', () => { + this.highlightService(serviceId); + }); + + node.addEventListener('mouseleave', () => { + this.unhighlightService(serviceId); + }); + + // Add pointer cursor via JavaScript (CSP-compliant) + node.style.cursor = 'pointer'; + }); + + this.addKeyboardNavigation(nodes); + + // Show initial state (overview) + this.showServiceDetails('overview'); + console.log('[InteractiveDiagram] Setup complete, showing overview'); + }; + // FIXED: Better load detection with SVG verification const checkAndInit = () => { const svgDoc = objectElement.contentDocument; @@ -263,52 +373,6 @@ class InteractiveDiagram { } } -if (typeof window !== 'undefined') { - window.interactiveDiagram = new InteractiveDiagram(); -} - -if (typeof module !== 'undefined' && module.exports) { - module.exports = InteractiveDiagram; -} - - // Listen for language changes and reload translations - handleLanguageChange() { - console.log('[InteractiveDiagram] Language changed, reloading translations'); - this.loadTranslations(); - // Re-render current service if one is active - if (this.activeService) { - const service = this.serviceData[this.activeService]; - if (service) { - this.renderServicePanel(service); - } - } - } -} - -// Initialize and listen for language changes -if (typeof window !== 'undefined') { - window.interactiveDiagram = new InteractiveDiagram(); - - // Listen for i18n initialization and language changes - window.addEventListener('i18nInitialized', () => { - if (window.interactiveDiagram) { - window.interactiveDiagram.handleLanguageChange(); - - // Listen for language changes and reload translations - handleLanguageChange() { - console.log('[InteractiveDiagram] Language changed, reloading translations'); - this.loadTranslations(); - // Re-render current service if one is active - if (this.activeService) { - const service = this.serviceData[this.activeService]; - if (service) { - this.renderServicePanel(service); - } - } - } -} - -// Initialize and listen for language changes if (typeof window !== 'undefined') { window.interactiveDiagram = new InteractiveDiagram();