Skip to content

131KB en.json statically imported by i18n — split into shell + lazy subsets #3535

@koala73

Description

@koala73

Summary

src/services/i18n.ts:5 statically imports the full English translation bundle:

import enTranslation from '../locales/en.json';

src/locales/en.json is 131,704 bytes (~30-40KB gzipped). Every page-load downloads + parses the entire dictionary, including keys that are only used by panels the user may never open.

The comment explicitly says "bundle it eagerly" because en is the fallback locale — but eager doesn't have to mean monolithic.

Likely fix

Two options, increasing complexity:

  1. Shell + lazy split: extract a small "essential keys" subset (header, nav, error toasts, panel chrome) into en.shell.json (target: <20KB). Keep that as the eager static import. Lazy-load the rest via import.meta.glob (mirrors the existing pattern at i18n.ts:15-18 for other locales). Panels load their slice on mount.

  2. Just lazy-load it all: remove the static import; use import.meta.glob for en too. Trade-off: first paint may show raw t('key.path') until the dictionary resolves. Mitigate with a tiny inline fallback for the few keys rendered before hydration.

Option 1 is the better tradeoff — it gives clean first paint while moving most of the weight off the critical path.

Severity

P0 (bundle weight). Compounds with the globe.gl issue — fixing both gives a meaningful first-paint win.

Related

  • src/services/i18n.ts:5 (static import)
  • src/locales/*.json (other locales already lazy via line 15-18)

Source

Manual code review (deepseek perf list, validated 2026-05-01).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Critical, blocks release or core functionalityarea: i18nInternationalization, translationsbugSomething isn't workingperformancePerformance optimization

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions