1/** 2 * Publications Component 3 * Dynamically renders scientific publications from translation data 4 * 5 * MAINTENANCE GUIDE: 6 * To add new papers, simply add entries to translations.js under: 7 * - "publications.arxiv" array for arXiv preprints 8 * - "publications.peer_reviewed" array for peer-reviewed papers 9 * 10 * Each paper needs: title, source, description, link 11 * The component will automatically render them in all languages! 12 */ 13 14// Wait for translations to load - check if already loaded or wait for event 15if (typeof window.translations !== 'undefined' && window.translations[window.currentLang || 'en']) { 16 // Translations already loaded, render immediately 17 renderPublications(); 18} else { 19 // Wait for translations to load 20 document.addEventListener('translationsLoaded', () => { 21 renderPublications(); 22 }); 23} 24 25function renderPublications() { 26 const currentLang = window.currentLang || 'en'; 27 const t = window.translations; 28 29 if (!t || !t[currentLang]) { 30 console.warn('[Publications] Translations not loaded for language:', currentLang); 31 return; 32 } 33 34 const langData = t[currentLang]; 35 36 if (!langData['publications.arxiv'] || !langData['publications.peer_reviewed']) { 37 console.warn('[Publications] Publication data not found in translations'); 38 return; 39 } 40 41 // Render arXiv preprints 42 const arxivContainer = document.getElementById('arxiv-publications-container'); 43 if (arxivContainer && langData['publications.arxiv']) { 44 arxivContainer.innerHTML = langData['publications.arxiv'].map(paper => createPaperCard(paper, 'arxiv')).join(''); 45 } 46 47 // Render peer-reviewed papers 48 const peerReviewedContainer = document.getElementById('peer-reviewed-publications-container'); 49 if (peerReviewedContainer && langData['publications.peer_reviewed']) { 50 peerReviewedContainer.innerHTML = langData['publications.peer_reviewed'].map(paper => createPaperCard(paper, 'peer-reviewed')).join(''); 51 } 52 53} 54 55function createPaperCard(paper, type) { 56 const currentLang = window.currentLang || 'en'; 57 const iconClass = type === 'arxiv' ? 'fa-file-alt' : 'fa-certificate'; 58 59 // Use translation function if available, otherwise fallback to English 60 const linkText = type === 'arxiv' 61 ? (window.t ? window.t('publications.link.arxiv') : 'Read on arXiv â') 62 : (window.t ? window.t('publications.link.pdf') : 'Read Paper (PDF) â'); 63 64 // NEW badge labels by language 65 const newBadgeText = { 66 'en': 'NEW', 67 'es': 'NUEVO', 68 'zh': 'æ°', 69 'ru': 'ÐÐÐÐÐ' 70 };
71 const badgeLabel = newBadgeText[currentLang] || 'NEW'; 72 73 // Add NEW badge if paper.new is true 74 const newBadge = paper.new ? `<span style="background: #00d4ff; color: #0a0a0a; font-size: 0.75em; padding: 3px 8px; border-radius: 4px; margin-left: 8px; font-weight: 700; vertical-align: middle;">${badgeLabel}</span>` : ''; 75 76 return ` 77 <div class="article-card"> 78 <h3>${escapeHtml(paper.title)}${newBadge}</h3> 79 <p class="source"><i class="fas ${iconClass}"></i> ${escapeHtml(paper.source)}</p> 80 <p>${escapeHtml(paper.description)}</p> 81 <a href="${escapeHtml(paper.link)}" target="_blank" rel="noopener"> 82 <i class="fas fa-external-link-alt"></i> ${linkText} 83 </a> 84 </div> 85 `; 86} 87 88function escapeHtml(text) { 89 const div = document.createElement('div'); 90 div.textContent = text; 91 return div.innerHTML; 92} 93
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.