feat(i18n): add language selector UI to docs page

Added interactive language switcher dropdown to make translations accessible:

UI Changes:
- Added language selector dropdown to docs.html header
- Flag emojis + language names (🇬🇧 English, 🇩🇪 Deutsch, 🇫🇷 Français)
- Positioned next to search button in page header

Functionality:
- Detect language from URL param, localStorage, or default to English
- Save language choice to localStorage for persistence
- Auto-reload document when language changes
- Update URL with ?lang= parameter
- Preserves selected document when switching languages

Implementation:
- Enhanced detectLanguage() to check URL > localStorage > i18n > default
- Added initLanguageSelector() IIFE to wire up dropdown
- Dropdown reflects current language on page load

User Experience:
- One-click language switching
- Language persists across page reloads
- Seamless document reload in new language
- URL updates to reflect language choice

🌐 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
TheFlow 2025-10-26 02:02:48 +13:00
parent 33e456cfa4
commit a608b838f5
2 changed files with 71 additions and 10 deletions

View file

@ -495,12 +495,25 @@
<h1 class="text-3xl font-bold text-gray-900">Framework Documentation</h1>
<p class="text-gray-600 mt-2">Technical specifications, guides, and reference materials</p>
</div>
<button type="button" id="open-search-modal-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition flex items-center gap-2" aria-label="Open search">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
<span>Search</span>
</button>
<div class="flex items-center gap-3">
<!-- Language Selector -->
<div class="relative">
<select id="language-selector"
class="px-4 py-2 bg-white border border-gray-300 rounded-lg hover:border-gray-400 transition text-sm font-medium text-gray-700 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
aria-label="Select language">
<option value="en">🇬🇧 English</option>
<option value="de">🇩🇪 Deutsch</option>
<option value="fr">🇫🇷 Français</option>
</select>
</div>
<!-- Search Button -->
<button type="button" id="open-search-modal-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition flex items-center gap-2" aria-label="Open search">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
<span>Search</span>
</button>
</div>
</div>
</div>
</div>

View file

@ -8,14 +8,28 @@ if (typeof DocumentCards !== 'undefined') {
documentCards = new DocumentCards('document-content');
}
// Detect language from i18n system
// Detect language from URL, localStorage, or i18n system
function detectLanguage() {
// Priority 1: URL parameter
const urlParams = new URLSearchParams(window.location.search);
const urlLang = urlParams.get('lang');
if (urlLang) {
return urlLang;
}
// Priority 2: localStorage
const storedLang = localStorage.getItem('tractatus_language');
if (storedLang) {
return storedLang;
}
// Priority 3: i18n system
if (window.I18n && window.I18n.currentLang) {
return window.I18n.currentLang;
}
// Fallback: Check URL parameter
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('lang') || 'en';
// Default: English
return 'en';
}
// Update URL with language parameter
@ -627,6 +641,40 @@ function closeToCModal() {
// Initialize
loadDocuments();
// Initialize language selector
(function initLanguageSelector() {
const selector = document.getElementById('language-selector');
if (!selector) return;
// Set initial value from current language
const initialLang = detectLanguage();
selector.value = initialLang;
currentLanguage = initialLang;
// Handle language change
selector.addEventListener('change', (e) => {
const newLang = e.target.value;
// Save to localStorage
localStorage.setItem('tractatus_language', newLang);
// Update current language
currentLanguage = newLang;
// Reload current document in new language
if (currentDocument) {
loadDocument(currentDocument.slug, newLang);
} else {
// If no document loaded yet, just update URL
const urlParams = new URLSearchParams(window.location.search);
const currentDoc = urlParams.get('doc');
if (currentDoc) {
loadDocument(currentDoc, newLang);
}
}
});
})();
// Add ESC key listener for closing modal
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {