feat(i18n): full internationalization — 14 locales, zero hardcoded English + Linux AppImage support#100
feat(i18n): full internationalization — 14 locales, zero hardcoded English + Linux AppImage support#100
Conversation
…es and add Linux AppImage config
…omponents - StrategicPosturePanel: 25 strings (military units, tooltips, timer) - App: 4 strings (GitHub link, pin map, filter, source counter) - StatusPanel: 5 strings (system status, timestamps, storage) - PizzIntIndicator: 3 strings + t() import (DEFCON, title, updated) - PlaybackControl: 2 strings + t() import (toggle mode, LIVE) - CountryBriefPage: 4 strings (share, print, export, source ref) - DeckGLMap: 4 strings + t() import (zoom controls, layer guide) - MonitorPanel: 2 strings (placeholder, no matches) - TechEventsPanel: 4 strings (loading, empty, show on map, more info) - TechReadinessPanel: 3 strings (internet, mobile, R&D tooltips) - Removed deb from tauri.conf.json build targets - Removed duplicate monitor key from en.json
…ck, Monitor, DeckGLMap - PizzIntIndicator: panel title, tensions title, source label, 6 status labels, 3 time-ago strings - PlaybackControl: Historical Playback header, LIVE button - MonitorPanel: Add Monitor button - DeckGLMap: 25 layer labels, 8 view selector options, Layers header, All button - Added ~50 new keys to en.json (English) and fr.json (French)
… 19 panels - Panel.ts base class: showLoading/showError defaults now use t() keys - Added 27 new common.* keys to en.json and fr.json - Updated 19 panel files with t() calls for loading/error messages - Added t() import to 12 panels: SatelliteFires, PopulationExposure, Displacement, ClimateAnomaly, StrategicRisk, Prediction, Cascade, GdeltIntel, NewsPanel, GeoHubs, Panel, PredictionPanel - All showLoading custom messages now translated (UCDP events, thermal data, ETF data, stablecoins, climate data, etc.) - All showError messages now translated (failed to load, no data, etc.)
…led sources strings - App.ts: 2 showError calls (All sources/Intel sources disabled) - PopulationExposurePanel: 'No exposure data available' panel-empty - SatelliteFiresPanel: 'No fire data available' panel-empty - UcdpEventsPanel: 'No events in this category' panel-empty - ClimateAnomalyPanel: 'No significant anomalies detected' panel-empty - export.ts: Export Data title + Export CSV/JSON button labels - Added 8 new common.* keys to en.json and fr.json - Added t() import to export.ts
- NewsPanel: Close button title attribute - CountryIntelModal: 4 component tooltip titles (Unrest/Conflict/Security/Information) - CIIPanel: Share story button + 4 component tooltip titles - Added common.unrest/conflict/security/information/shareStory keys to en.json/fr.json
…riefPage - CountryBriefPage: 2 aria-label='Close' + 3 export labels (Image/JSON/CSV) - Added exportImage key to en.json and fr.json - Expanded common section with ~48 native-translated keys in: de.json (German), es.json (Spanish), it.json (Italian), pl.json (Polish), nl.json (Dutch), pt.json (Portuguese), sv.json (Swedish) - Also translated base nl/pt/sv common keys that were still in English
- Restructure popups keys in de/es/it/pl/nl/pt/sv to match en.json nested structure - Move orphaned top-level keys (earthquake, base, protest, flight, nuclear, cable, pipeline, etc.) into popups.* namespace - Add full native translations for ~200 popup keys per locale - Ensures i18next resolves popups.* keys correctly for all languages
"here" and other basic English words (pronouns, prepositions, adverbs) were not in SUPPRESSED_TRENDING_TERMS, causing false keyword spike findings for common words.
…ages Audit found missing keys in all non-EN locales (62-90 per file) and 25 stale keys in PT/NL/SV. Fixes gaps, removes stale keys, corrects FR infra key misplacement, and adds complete Russian (ru) translation with 1013/1013 keys matching the English reference.
When the NER model isn't loaded, isSignificantTerm was returning true for all terms, letting common words like "here" trigger keyword spike findings. Now falls back to a capitalization heuristic: single-word terms must appear capitalized (mid-sentence) in >50% of headlines to be treated as significant. Also added ~45 missing English stopwords.
Shows a compact pill badge (bottom-right) inviting users to the GitHub Discussions page. Includes pulsing dot indicator, CTA button, close button, and "Don't show again" option that persists to localStorage.
- Add ar.json and zh.json translations (1013 keys each, full parity) - RTL support: dir="rtl" on <html>, targeted CSS overrides in rtl-overrides.css - Font fallbacks: system Arabic/CJK fonts via --font-body CSS variable - i18n.ts: RTL_LANGUAGES set, applyDocumentDirection(), isRTL(), getLocale() - story-renderer.ts: locale-aware date formatting via getLocale() - Type declarations for both new locales
…TC clock Replace hardcoded English text with t() calls across 12 source files: signal context descriptions, alert titles/summaries, intel topic names, map legend labels, asset/threat labels, UCDP panel headers, stablecoin/status panel sections. Add ~114 new keys to en.json and translate to all 11 locales (fr/de/es/it/pl/pt/nl/sv/ru/ar/zh). Remove dead #timeDisplay span that was never updated by JS. All 12 locales at 1127-key parity with 0 placeholder mismatches.
…AppImage, locale gaps, lang normalization
- Fix relative-time {{count}} placeholders in all 12 locales (5m ago, not m ago)
- Localize CommunityWidget: replace 3 hardcoded English strings with t() calls
- Add Linux AppImage to tech/finance Tauri configs, CI matrix (ubuntu-22.04), packaging scripts, and download-node.sh
- Fix language code normalization: add supportedLngs/nonExplicitSupportedLngs to i18next, normalize getCurrentLanguage()
- Translate ~240 untranslated English strings across 11 locale files (ru/ar/zh now 100% translated)
- Add components.community section to all 12 locales
- All 12 locales at 1130-key parity, 0 placeholder mismatches
applyDocumentDirection() now splits on '-' before checking RTL set, so ar-SA correctly triggers dir="rtl" on first detect.
- CommunityWidget: aria-label="Close" → t('common.close')
- App.ts: ' (current)' suffix → t('common.currentVariant')
- fr.json: "Cloud & Infrastructure" → "Cloud et infrastructure"
- sv.json: "24h Vol" → "24t volym"
- Added common.close + common.currentVariant to all 12 locales
New ja.json with full translation parity to en.json. Registered in i18n.ts: import, resources, supportedLngs, LANGUAGES, getLocale map.
t() always returns a string (key itself if missing), so || 'English' fallbacks were unreachable dead code.
t() always returns a string, so || 'English' fallbacks were unreachable. Removed all 15 instances.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79f9f493b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| this.allNews = collectedNews; | ||
| this.initialLoadComplete = true; | ||
| maybeShowDownloadBanner(); | ||
| mountCommunityWidget(); |
There was a problem hiding this comment.
Mount community widget only once per session
mountCommunityWidget() is invoked inside loadNews(), and setupRefreshIntervals() schedules loadNews() repeatedly, so each refresh appends another .community-widget when the user has not dismissed it permanently. Because mountCommunityWidget() has no idempotency guard, long-running sessions can accumulate duplicate floating widgets (and duplicate click handlers), which degrades the UI and can confuse users.
Useful? React with 👍 / 👎.
src/components/RuntimeConfigPanel.ts
Outdated
There was a problem hiding this comment.
Ignore missing i18n keys for runtime help text
The help text now comes from t(modals.runtimeConfig.help.${key}), but many secret keys do not have corresponding translations, and i18next returns the lookup key string in that case; since that value is truthy, the panel renders raw key paths (for example modals.runtimeConfig.help.GROQ_API_KEY) instead of omitting help text. This is a regression from the previous partial-help behavior and makes the settings UI noisy and misleading unless every secret key gets a translation entry.
Useful? React with 👍 / 👎.
Main variant: NHK World + Nikkei Asia in asia category. Finance variant: Nikkei Asia in markets category. Added asia.nikkei.com to RSS proxy allowlist.
…keys - CommunityWidget: add DOM check to prevent duplicate widgets on repeated loadNews() calls - RuntimeConfigPanel: compare t() result against key path to suppress missing help translations
|
Thanks again @Lib-LOCALE |
Summary
t()callst() || 'English') removed from all componentsKey changes
src/services/i18n.ts— i18next setup with language detection, RTL, locale switchingsrc/locales/src/styles/rtl-overrides.css+src/styles/lang-switcher.csst()instead of hardcoded strings.github/workflows/build-desktop.yml— Linux CI matrixscripts/desktop-package.mjs+download-node.sh— Linux target supportTest plan
dir="rtl"on<html>, layout mirrors{{count}}interpolation works in timeAgo stringstsc --noEmitpasses (confirmed locally)