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
This commit is contained in:
parent
0a2df38207
commit
c4e54502da
2 changed files with 114 additions and 50 deletions
|
|
@ -251,7 +251,7 @@
|
||||||
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.validator.name"></h3>
|
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.validator.name"></h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
||||||
Validates AI actions against instruction history. Aims to prevent pattern bias overriding explicit directives.
|
<span data-i18n="services.validator.description"></span>
|
||||||
</p>
|
</p>
|
||||||
<div class="text-xs rounded px-3 py-2" class="badge-validator" data-i18n-html="services.validator.promise">
|
<div class="text-xs rounded px-3 py-2" class="badge-validator" data-i18n-html="services.validator.promise">
|
||||||
<strong>Early Promise:</strong> Independent verification—AI claims checked against external source.
|
<strong>Early Promise:</strong> Independent verification—AI claims checked against external source.
|
||||||
|
|
@ -268,7 +268,7 @@
|
||||||
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.pressure.name"></h3>
|
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.pressure.name"></h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
||||||
Monitors AI performance degradation. Escalates when context pressure threatens quality.
|
<span data-i18n="services.pressure.description"></span>
|
||||||
</p>
|
</p>
|
||||||
<div class="text-xs rounded px-3 py-2" class="badge-pressure" data-i18n-html="services.pressure.promise">
|
<div class="text-xs rounded px-3 py-2" class="badge-pressure" data-i18n-html="services.pressure.promise">
|
||||||
<strong>Early Promise:</strong> Objective metrics may detect manipulation attempts early.
|
<strong>Early Promise:</strong> Objective metrics may detect manipulation attempts early.
|
||||||
|
|
@ -285,7 +285,7 @@
|
||||||
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.metacognitive.name"></h3>
|
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.metacognitive.name"></h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
||||||
Requires AI to pause and verify complex operations before execution. Structural safety check.
|
<span data-i18n="services.metacognitive.description"></span>
|
||||||
</p>
|
</p>
|
||||||
<div class="text-xs rounded px-3 py-2" class="badge-metacognitive" data-i18n-html="services.metacognitive.promise">
|
<div class="text-xs rounded px-3 py-2" class="badge-metacognitive" data-i18n-html="services.metacognitive.promise">
|
||||||
<strong>Early Promise:</strong> Architectural gates aim to enforce verification steps.
|
<strong>Early Promise:</strong> Architectural gates aim to enforce verification steps.
|
||||||
|
|
@ -302,7 +302,7 @@
|
||||||
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.deliberation.name"></h3>
|
<h3 class="text-lg font-bold text-gray-900 break-words overflow-wrap-anywhere" data-i18n="services.deliberation.name"></h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
<p class="text-gray-600 text-sm mb-3 break-words overflow-wrap-anywhere">
|
||||||
Facilitates multi-stakeholder deliberation for values conflicts. AI provides facilitation, not authority.
|
<span data-i18n="services.deliberation.description"></span>
|
||||||
</p>
|
</p>
|
||||||
<div class="text-xs rounded px-3 py-2" class="badge-deliberation" data-i18n-html="services.deliberation.promise">
|
<div class="text-xs rounded px-3 py-2" class="badge-deliberation" data-i18n-html="services.deliberation.promise">
|
||||||
<strong>Early Promise:</strong> Human judgment required—architecturally enforced escalation for values.
|
<strong>Early Promise:</strong> Human judgment required—architecturally enforced escalation for values.
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,116 @@ class InteractiveDiagram {
|
||||||
console.log('[InteractiveDiagram] Loaded translations for', Object.keys(this.serviceData).length, 'services');
|
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 <object> 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
|
// FIXED: Better load detection with SVG verification
|
||||||
const checkAndInit = () => {
|
const checkAndInit = () => {
|
||||||
const svgDoc = objectElement.contentDocument;
|
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') {
|
if (typeof window !== 'undefined') {
|
||||||
window.interactiveDiagram = new InteractiveDiagram();
|
window.interactiveDiagram = new InteractiveDiagram();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue