🔧 Programmierung 🕛 vor 3 Monaten 4 Min Lesezeit
0

How I built a multilingual news SPA in vanilla JS — architecture notes

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

NewsScope is a real-time news search engine: search a topic, filter by language, category and country, get live results from the NewsData.io API. No React, no bundler, no npm dependencies — just HTML, CSS and vanilla ES2020+.



This post is about a few specific decisions in the architecture that I think are worth sharing.









The module structure



The JS is 9 files, each with a single responsibility, loaded in dependency order directly in index.html:




CODE
config.js   →  i18n.js   →  data.js
↓ ↓ ↓
helpers.js → geo.js → ui.js
↓ ↓ ↓
render.js → api.js → main.js






Every module only uses things defined in modules loaded before it. main.js registers all event listeners and calls init() — it's the only file that touches everything. config.js is the smallest file in the project, since it only defines the state object and two constants.



All app state lives in a single flat object in config.js, accessed as a global:




CODE
const S = {
apiKey: '', query: '', activeQuery: '',
language: 'es', category: '', country: '',
results: [], nextPage: null,
loading: false, hasSearched: false, error: null,
};






No state management library. When something changes, the relevant render function gets called explicitly. Simple, and easy to trace.









Translating search intent, not just the UI



Most i18n stops at labels and button text. NewsScope has 10 predefined topic shortcuts (AI, Climate, Economy, Cybersecurity…) that trigger a search. If a user picks "Cybersecurity" while the app is set to Japanese, the keyword sent to the API should be in Japanese — not a transliteration of the English word.



The solution is a TOPIC_KEYWORDS map in data.js:




CODE
const TOPIC_KEYWORDS = {
ai: { es: 'inteligencia artificial', en: 'artificial intelligence', ja: '人工知能', ar: 'الذكاء الاصطناعي', /* 7 more */ },
cyber: { es: 'ciberseguridad', en: 'cybersecurity', ja: 'サイバーセキュリティ', /* 8 more */ },
// 8 more topics
};






One string per language, per topic. Switching the UI language and then selecting a topic sends the right keyword for that language. The results are genuinely different.









Geo-restriction detection



Some news sources (NYT, WSJ, The Times, Le Monde…) block readers outside certain countries. Finding out after you've already clicked the link is annoying.



NewsScope checks the article URL before opening it. If the domain matches a known geo-restricted list, it shows a warning modal first with the option to continue anyway — or to disable the warning permanently (saved in localStorage, so it persists across sessions until the user clears their storage).




CODE
function isLikelyGeoRestricted(url) {
try {
const host = new URL(url).hostname.replace(/^www\./, '');
return GEO_RESTRICTED.some(d => host === d || host.endsWith('.' + d));
} catch { return false; }
}






It's a static list, so it won't catch every case. But it handles the most common ones and the pattern is easy to extend.









Error handling that's actually useful



A search app with a generic "Something went wrong" message on every failure is frustrating to use. api.js maps every known failure to a specific, translated message with recovery actions:




CODE
function parseError(err) {
if (err.name === 'AbortError') return t('errTimeout'); // 12s hard limit
if (!navigator.onLine) return t('errOffline');
if (err.type === 'auth') return t('errAuth'); // bad or expired key
if (err.type === 'limit') return t('errLimit'); // rate limited
if (err.type === 'server') return t('errServer');
if (err.code === 'ParametersMissing' || ...) return t('errParams', err.msg);
return t('errGeneric', err.msg);
}






Each error type renders with contextual action buttons ("Change key", "Try again") so the user always has a clear next step. And since the error messages go through the same t() function as everything else, they're translated too.









Tradeoffs and future improvements



ES modules — Loading 9 scripts in a fixed order works, but native type="module" would make the dependency graph explicit and statically analyzable. The reason for not using them: opening index.html directly from the filesystem (file://) blocks module imports in some browsers, and keeping zero-server-required as a constraint felt worthwhile. A future version could drop that constraint and adopt ES modules without changing any other part of the architecture.



API key explanation in the UI — The key is stored in localStorage and requests go directly from your browser to newsdata.io — no intermediary server involved. The README covers this, but surfacing that context inside the app itself would be a better experience for users who don't read documentation before using a tool.









Try it



Free API key at · GitHub



Any suggestions for improving this would be greatly appreciated. 🙌​

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
6 Quellen
CVE-2022-44255 | TOTOLINK LR350 9.3.5u.6369_B20220309 buffer overflow (EUVD-2022-47204)
2 Quellen
CVE-2026-68426 | Linux Kernel up to 6.18.41/7.1.5/7.2-rc3 xfrm validate_xmit_skb_list use after free (Nessus ID 346426)
1 Quelle
Windows 11 Probleme mit gültiger Domänenanmeldung nach September-Update [Workaround]
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How I built a multilingual news SPA in vanilla JS — architecture notes

Thematisch verwandte Begriffe: built, multilingual, news, vanilla · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...