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:
parent
33e456cfa4
commit
a608b838f5
2 changed files with 71 additions and 10 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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') {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue