# Footer i18n Translation Failure - Technical Diagnostic Brief **Date**: 2025-10-22 **Issue**: Footer displays raw translation keys instead of translated text on /researcher.html and /leader.html **Status**: BLOCKING - Prevents deployment **Affected Pages**: /researcher.html, /leader.html **Working Pages**: /index.html, /implementer.html --- ## Problem Statement Footer component renders correctly but translations fail to apply. Elements display raw keys like `footer.about_heading` instead of "Tractatus Framework". **Console Output Shows:** ``` [Footer] Applying translations... [Footer] Footer exists: true [Footer] Elements with data-i18n: 20 [Footer] Translations applied [Footer] about_heading element text: footer.about_heading ← PROBLEM ``` **Expected**: `about_heading element text: Tractatus Framework` --- ## System Architecture ### Translation System - **Library**: Custom i18n implementation (`/public/js/i18n-simple.js`) - **Translation files**: `/public/locales/en/common.json`, `/public/locales/en/researcher.json` - **Loading strategy**: Async fetch → shallow merge - **Application method**: `window.I18n.applyTranslations()` replaces `innerHTML` of `[data-i18n]` elements ### Footer Component - **File**: `/public/js/components/footer.js` - **Type**: Dynamically inserted component (not in static HTML) - **Initialization**: Event-based (waits for `i18nInitialized` event) - **Cache version**: `?v=1761129862` --- ## Diagnostic Evidence ### 1. Translation Data Verified on Server ```bash $ curl -s http://localhost:9000/locales/en/common.json | jq '.footer.about_heading' "Tractatus Framework" ✓ CORRECT $ curl -s http://localhost:9000/locales/en/researcher.json | jq 'has("footer")' false ✓ CORRECT (footer removed to prevent overwrite) ``` ### 2. Footer Rendering Confirmed ```javascript [Footer] Footer exists: true [Footer] Elements with data-i18n: 20 ``` Footer HTML is in DOM with proper `data-i18n` attributes. ### 3. Translation Application Called ```javascript [Footer] Translations applied ``` `window.I18n.applyTranslations()` executes without errors. ### 4. Translation Fails ```javascript [Footer] about_heading element text: footer.about_heading ``` After `applyTranslations()`, element still contains raw key. --- ## Root Cause Hypothesis **`window.I18n.t('footer.about_heading')` is returning the key instead of the translation.** ### i18n.t() Implementation ```javascript // /public/js/i18n-simple.js:123-136 t(key) { const keys = key.split('.'); let value = this.translations; for (const k of keys) { if (value && typeof value === 'object') { value = value[k]; } else { return key; // Return key if translation not found } } return value || key; } ``` **Possible failures:** 1. `this.translations` doesn't have `footer` key 2. `this.translations.footer` doesn't have `about_heading` key 3. Value is not a string (e.g., still an object) 4. Timing issue - translations not yet loaded when `applyTranslations()` called --- ## Critical Question **What does `window.I18n.translations` contain when footer renders?** ### Diagnostic Step Required **In browser console, run:** ```javascript console.log('Full translations:', window.I18n.translations); console.log('Footer object:', window.I18n.translations.footer); console.log('about_heading:', window.I18n.translations.footer?.about_heading); console.log('Test t():', window.I18n.t('footer.about_heading')); ``` **Expected output:** ```javascript Full translations: {footer: {...}, page: {...}, header: {...}, sections: {...}} Footer object: {about_heading: "Tractatus Framework", ...} about_heading: "Tractatus Framework" Test t(): "Tractatus Framework" ``` **If output differs**, this reveals where the data structure breaks. --- ## Working vs Broken Comparison ### Working Pages (index.html, implementer.html) - **Script order**: `i18n-simple.js` → `language-selector.js` → `scroll-animations.js` → `page-transitions.js` → `footer.js` - **Footer in page-specific JSON**: NO - **Result**: Footer displays correctly ### Broken Pages (researcher.html, leader.html) - **Script order**: `i18n-simple.js` → `language-selector.js` → `scroll-animations.js` → `page-transitions.js` → `version-manager.js` → `researcher-page.js` → `footer.js` - **Footer in page-specific JSON**: Removed (was causing shallow merge issue) - **Result**: Footer displays raw keys **Key difference**: Extra scripts (`version-manager.js`, `researcher-page.js`) load between i18n and footer. --- ## Previous Fixes Attempted ### Fix 1: Consolidated footer translations (v1.1.8) **Problem**: researcher.json and leader.json had partial `footer` objects that overwrote common.json footer during shallow merge. **Action**: Moved all footer keys to common.json, removed from page-specific files. **Result**: Data structure fixed on server, but translations still not applied. ### Fix 2: Event-based initialization (v1.1.9) **Problem**: Race condition - footer rendering before i18n loaded. **Action**: Wait for `i18nInitialized` event before rendering. **Result**: Timing fixed (console confirms footer waits for i18n), but translations still fail. ### Fix 3: Removed polling (v1.2.0) **Problem**: Polling logic triggered rate limiting (100 req/15min). **Action**: Simplified to single event-based check. **Result**: Rate limiting resolved, but core translation issue persists. --- ## Next Debugging Steps ### Step 1: Inspect Browser Runtime State ```javascript // In browser console on /researcher.html after page load: window.I18n.translations window.I18n.t('footer.about_heading') document.querySelector('footer [data-i18n="footer.about_heading"]').innerHTML ``` ### Step 2: Compare Working Page ```javascript // In browser console on /index.html after page load: window.I18n.translations window.I18n.t('footer.about_heading') document.querySelector('footer [data-i18n="footer.about_heading"]').innerHTML ``` ### Step 3: Check Translation Merge ```javascript // Does researcher.json override common.json at runtime? // Expected: common.json footer + researcher.json sections // Actual: ??? ``` --- ## Potential Solutions ### Solution A: Deep Merge Instead of Shallow Merge **Current code** (`i18n-simple.js:111`): ```javascript this.translations = { ...commonTranslations, ...pageTranslations }; ``` **Problem**: Shallow merge overwrites entire top-level objects. **Fix**: Deep merge utility ```javascript this.translations = deepMerge(commonTranslations, pageTranslations); function deepMerge(target, source) { const output = { ...target }; for (const key in source) { if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { output[key] = deepMerge(target[key] || {}, source[key]); } else { output[key] = source[key]; } } return output; } ``` ### Solution B: Namespace Separation **Keep footer translations ONLY in common.json** **Never put footer keys in page-specific files** **Status**: Already implemented, but verify runtime state ### Solution C: Manual Footer Translation **Instead of relying on global `applyTranslations()`:** ```javascript applyFooterTranslations() { const footerElements = document.querySelectorAll('footer [data-i18n]'); footerElements.forEach(el => { const key = el.dataset.i18n; const translation = window.I18n.t(key); console.log(`Translating ${key} -> ${translation}`); el.innerHTML = translation; }); } ``` --- ## File Locations ### Translation Files - `/public/locales/en/common.json` - Contains full footer object - `/public/locales/en/researcher.json` - No footer object (removed) - `/public/locales/en/leader.json` - No footer object (removed) ### JavaScript Files - `/public/js/i18n-simple.js` - Translation system core - `/public/js/components/footer.js` - Footer component - `/public/researcher.html:627` - Footer script tag with cache version - `/public/leader.html:611` - Footer script tag with cache version ### Server Configuration - `/src/server.js:77` - Rate limiting middleware (100 req/15min) - `/src/middleware/rate-limit.middleware.js` - Rate limiter implementation --- ## Success Criteria **Footer displays:** ``` Tractatus Framework (not footer.about_heading) Documentation (not footer.documentation_heading) Framework Docs (not footer.documentation_links.framework_docs) ...etc ``` **Console shows:** ``` [Footer] about_heading element text: Tractatus Framework ``` --- ## Contact for Clarification **Project Owner**: Review console output from browser **Required**: Share `window.I18n.translations` object from browser console **This will immediately reveal** if the problem is: - Data not loaded (translations object missing footer) - Data structure wrong (footer exists but wrong shape) - Translation function broken (t() not navigating object correctly) - Application timing (translations loaded but not applied) --- **Priority**: HIGH - Blocking deployment **Estimated Debug Time**: 15-30 minutes with browser console access **Complexity**: LOW - Simple data flow issue, just need to see runtime state