Ingglish Architecture: How the Translator Works

Architecture Overview

High-level architecture of the Ingglish project.

Project Structure

ingglish/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ normalize/      # Text cleanup, case handling, tokenization, word patterns
β”‚   β”œβ”€β”€ phonemes/       # Phoneme data + conversion
β”‚   β”œβ”€β”€ dictionary/     # CMU dict, lookup, frequency
β”‚   β”œβ”€β”€ g2p/            # Rule-based grapheme-to-phoneme
β”‚   β”œβ”€β”€ ipa/            # IPA ↔ ARPAbet conversion
β”‚   β”œβ”€β”€ shavian/        # Shavian alphabet conversion
β”‚   β”œβ”€β”€ deseret/        # Deseret alphabet conversion
β”‚   β”œβ”€β”€ fallback/       # Unknown word strategies
β”‚   β”œβ”€β”€ core/           # Translation API (translate + reverse)
β”‚   β”œβ”€β”€ dom/            # DOM translation utilities
β”‚   β”œβ”€β”€ website/        # React web application
β”‚   β”œβ”€β”€ extension/      # Chrome extension
β”‚   └── cors-proxy/     # Cloudflare Worker proxy
β”œβ”€β”€ docs/               # Documentation
└── .github/            # CI/CD workflows

Package Dependencies

@ingglish/normalize (0 deps)
@ingglish/phonemes  (0 deps) ◄┐
@ingglish/dictionary (0 deps) ◄─
@ingglish/g2p ──► phonemes    ◄┼── @ingglish/fallback
                               β”‚
@ingglish/ipa ──► phonemes     β”‚
@ingglish/shavian ──► phonemes + dictionary
@ingglish/deseret ──► phonemes + dictionary
                               β”‚
ingglish ◄── all above packages
       β–²
@ingglish/dom ──► @ingglish/normalize (peer: core)
       β–²
@ingglish/website ──► @ingglish/dom + ingglish
@ingglish/extension ──► ingglish

Library Packages

@ingglish/normalize - Text cleanup, case handling, tokenization

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ case.ts             # Case pattern detection/application, splitCamelCase
β”œβ”€β”€ text.ts             # normalizeApostrophes, stripDiacritics, URL/email preservation
└── tokenize.ts         # WORD_SPLIT_REGEX, WORD_TEST_REGEX, tokenizeText, tokenizeIPA, etc.

@ingglish/phonemes - Phoneme data + conversion

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ arpabet.ts          # ARPAbet phoneme definitions
β”œβ”€β”€ phonotactics.ts     # English sound rules for stress
β”œβ”€β”€ types.ts            # OutputFormat type
β”œβ”€β”€ to-ingglish.ts      # ARPAbet β†’ Ingglish
β”œβ”€β”€ from-ingglish.ts    # Ingglish β†’ ARPAbet
β”œβ”€β”€ ingglish-maps.ts    # Phoneme mapping tables
β”œβ”€β”€ custom-format.ts    # Custom format registration
└── format-registry.ts  # Format registry for extensible output

@ingglish/dictionary - CMU dict, lookup, frequency

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ loader.ts           # Load and cache CMU dictionary
β”œβ”€β”€ lookup.ts           # Word pronunciation lookup
β”œβ”€β”€ reverse.ts          # Build reverse index (phoneme β†’ words)
β”œβ”€β”€ frequency.ts        # Word frequency ranking
β”œβ”€β”€ custom-words.ts     # Custom pronunciations (tech terms)
└── data/               # Generated dictionary and frequency data

@ingglish/g2p - Rule-based grapheme-to-phoneme

src/
β”œβ”€β”€ index.ts            # Public API
β”œβ”€β”€ g2p-rules.ts        # Core G2P conversion rules
β”œβ”€β”€ stress.ts           # Stress assignment
└── stress.test.ts      # Stress prediction tests

@ingglish/ipa - IPA ↔ ARPAbet conversion

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ to-ipa.ts           # ARPAbet β†’ IPA with stress
└── from-ipa.ts         # IPA β†’ ARPAbet

@ingglish/shavian - Shavian alphabet conversion

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ to-shavian.ts       # ARPAbet β†’ Shavian
β”œβ”€β”€ from-shavian.ts     # Shavian β†’ ARPAbet
β”œβ”€β”€ shavian-maps.ts     # Shavian mapping tables
└── tokenize.ts         # Shavian tokenization

@ingglish/deseret - Deseret alphabet conversion

src/
β”œβ”€β”€ index.ts            # Barrel exports
β”œβ”€β”€ to-deseret.ts       # ARPAbet β†’ Deseret
β”œβ”€β”€ from-deseret.ts     # Deseret β†’ ARPAbet
β”œβ”€β”€ deseret-maps.ts     # Deseret mapping tables
└── tokenize.ts         # Deseret tokenization

@ingglish/fallback - Unknown word strategies

src/
β”œβ”€β”€ index.ts            # Fallback orchestration
β”œβ”€β”€ acronyms.ts         # Acronym/initialism handling
β”œβ”€β”€ compounds.ts        # Compound word splitting
β”œβ”€β”€ stemming.ts         # Base word + suffix matching
└── british.ts          # British spelling variants

ingglish - Translation API

The core package is a thin orchestration layer. It imports from the packages above and exports the public translation API.

src/
β”œβ”€β”€ index.ts            # Public API: translate, reverseTranslate, Sync variants
β”œβ”€β”€ dict-loader.ts      # Per-language dictionary registration/loading
β”œβ”€β”€ register-english.ts # Registers the English dictionary loader
└── translate/          # Translation logic
    β”œβ”€β”€ index.ts        # Re-exports the translate/reverse API
    β”œβ”€β”€ forward.ts      # English β†’ Ingglish/IPA (incl. contractions)
    β”œβ”€β”€ reverse.ts      # Ingglish/IPA β†’ English (incl. contractions)
    β”œβ”€β”€ pipeline.ts     # Shared tokenize β†’ map β†’ render stages
    └── preserved.ts    # URL/email preservation during translation

Contraction handling ("don't", "I'm") lives inline in forward.ts/reverse.ts; there is no separate contractions or language-detection module.

Translation Flow

English Text
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  translateText  β”‚ (format: 'ingglish' | 'ipa')
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ tokenize
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ translateWord   │────>β”‚ lookupPronunciation  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚
         β”‚ found?                β”‚ CMU Dictionary
         β”‚                       β”‚
    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”                  β”‚
    β”‚         β”‚                  β–Ό
    β–Ό         β–Ό           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 phonemes   unknown       β”‚   phonemes   β”‚
    β”‚         β”‚           β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚         β”‚                  β”‚
    β”‚    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”             β”‚
    β”‚    β”‚ stemmingβ”‚             β”‚
    β”‚    β”‚  rules  β”‚             β”‚
    β”‚    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜             β”‚
    β”‚         β”‚                  β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                  β”‚
         β”‚                       β”‚
         β–Ό                       β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚   Output Format?   β”‚<β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
    β”‚         β”‚
    β–Ό         β–Ό
Ingglish    IPA
    β”‚         β”‚
    β–Ό         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ phonemes  β”‚ β”‚phonemesTo β”‚
β”‚ToIngglish β”‚ β”‚   IPA     β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
      β”‚             β”‚
      β–Ό             β–Ό
 "haloh"       "/hΙ™Λˆloʊ/"

Reverse Translation Flow

Supports both Ingglish and IPA input:

Ingglish Text          IPA Text
     β”‚                     β”‚
     β–Ό                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚reverseTranslate β”‚  β”‚ reverseTranslate   β”‚
β”‚     Text        β”‚  β”‚     IPAText        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                     β”‚
         β–Ό                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ingglishToPhonemes  β”‚  β”‚   ipaToArpabet     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                       β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
                      β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚  lookupByPhonemes   β”‚  Reverse dictionary lookup
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚   sortByFrequency   β”‚  Rank homophones
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
            English Text (most common match)

Key Data Structures

CMU Dictionary

// Word β†’ Phoneme array (pre-split at build time)
{
  "hello": ["HH", "AH0", "L", "OW1"],
  "world": ["W", "ER1", "L", "D"],
  ...
}

Reverse Dictionary (built at runtime)

// Phoneme key β†’ English words (sorted by frequency)
Map<string, string[]>
{
  "T UW": ["to", "too", "two"],
  "DH EH R": ["there", "their", "they're"],
  ...
}

Phoneme Map

// ARPAbet β†’ Ingglish spelling
{
  "HH": "h",
  "AH": "uh",
  "L": "l",
  "OW": "oh",
  ...
}

DOM Library (@ingglish/dom)

Browser-only utilities for translating DOM content.

Module Structure

src/
β”œβ”€β”€ index.ts                    # Public API exports
β”œβ”€β”€ types.ts                    # DOMTranslatorOptions interface
β”œβ”€β”€ translate/                  # DOM translation logic
β”‚   β”œβ”€β”€ index.ts                # translateDOM orchestration
β”‚   β”œβ”€β”€ translator.ts           # Core DOM translation algorithm
β”‚   β”œβ”€β”€ apply-map.ts            # Apply pre-computed translations
β”‚   β”œβ”€β”€ chunked.ts              # requestAnimationFrame chunked processing
β”‚   β”œβ”€β”€ restore.ts              # Restore original text
β”‚   └── tooltip-fragment.ts     # Hover tooltip HTML generation
└── traversal/                  # DOM traversal
    β”œβ”€β”€ index.ts                # Traversal exports
    β”œβ”€β”€ browser.ts              # Browser detection
    β”œβ”€β”€ extract.ts              # Word extraction from text nodes
    β”œβ”€β”€ skip-rules.ts           # Skip logic for tags/classes
    β”œβ”€β”€ text-nodes.ts           # TreeWalker and text node utilities
    └── tooltip.ts              # Tooltip styling utilities

Public API: translateDOM / translateDOMSync, restoreDOM, and applyTranslationsMap, plus traversal helpers (collectTextNodes, extractWordsFromNodes, injectTooltipStyles, injectTooltipBehavior).

Key Features

  • Chunked translation: Uses requestAnimationFrame for smooth rendering on large pages
  • Tooltip support: Wraps translated words in spans with original text on hover
  • Attribute translation: Handles title, alt, placeholder, aria-label
  • Skip logic: Respects <code>, <pre>, .no-translate, contenteditable
  • Pre-computed translations: applyTranslationsMap() for external translation sources

Live MutationObserver handling (auto-translating dynamically added content) is implemented in the Chrome extension's content script, not in this package.

Website (@ingglish/website)

React single-page application with three main features:

Components

src/
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ TextTranslator.tsx   # Bidirectional text translation
β”‚   β”œβ”€β”€ UrlTranslator.tsx    # Web page translation
β”‚   β”œβ”€β”€ SpellingGuide.tsx    # Phoneme mapping reference
β”‚   β”œβ”€β”€ Extension.tsx        # Chrome extension info page
β”‚   └── Docs.tsx             # Documentation viewer
β”œβ”€β”€ contexts/
β”‚   └── FormatContext.tsx    # Output format state (Ingglish/IPA)
β”œβ”€β”€ hooks/
β”‚   └── useUrlTranslator.ts  # URL fetching & translation logic
└── App.tsx                   # Tab navigation & routing

URL Translation Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Browser   │────>β”‚ CORS Proxy  │────>β”‚ Target Site  β”‚
β”‚   (iframe)  β”‚     β”‚  (Worker)   β”‚     β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ translateDOMβ”‚  In-place DOM modification
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. User enters URL
  2. Website fetches via CORS proxy
  3. HTML is written to sandboxed iframe
  4. translateDOM from @ingglish/dom walks text nodes and translates
  5. Links are intercepted for navigation within iframe

Chrome Extension (@ingglish/extension)

Components

src/
β”œβ”€β”€ manifest.json     # Extension configuration
β”œβ”€β”€ content-script.ts   # Content script (DOM walking + message passing)
β”œβ”€β”€ background.ts     # Service worker (holds dictionary ~5MB)
└── popup.ts          # Popup UI

Architecture

The extension uses a message-passing architecture to keep the content script lightweight:

  • Background service worker: Loads the full CMU dictionary (~5MB) once
  • Content script: Lightweight (~11KB), walks DOM and sends words to background for translation
  • Translation cache: 50K entry in-memory cache in background for fast repeated lookups

Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Popup UI   │────>β”‚   Message    β”‚
β”‚ (popup.ts)   β”‚     β”‚   Passing    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Content Script (content-script.ts)    β”‚
β”‚  β€’ Walks DOM, collects text nodes                β”‚
β”‚  β€’ Sends batches of words to background          β”‚
β”‚  β€’ Applies translations in chunks (RAF)          β”‚
β”‚  β€’ Debounced MutationObserver (100ms)            β”‚
β”‚  β€’ In-place span updates for format switching    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ chrome.runtime.sendMessage
                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Background (background.ts)          β”‚
β”‚  β€’ Loads CMU dictionary on startup               β”‚
β”‚  β€’ Caches translations (50K entries, FIFO)       β”‚
β”‚  β€’ Returns translated words                      β”‚
β”‚  β€’ Manages tab-specific translation state        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Performance Optimizations

  1. Debounced MutationObserver: Waits 100ms for mutations to settle before processing, preventing freezes on sites with rapid DOM updates (e.g., infinite scroll)

  2. In-place format switching: When switching between Ingglish and IPA, updates existing spans directly instead of restoring and re-translating the entire page

  3. Chunked DOM updates: Uses requestAnimationFrame to apply translations in chunks of 50 elements, keeping the main thread responsive

  4. Pre-collected text nodes: Passes pre-collected nodes to applyTranslationsMap() to avoid double DOM traversal

CORS Proxy (@ingglish/cors-proxy)

Cloudflare Worker that proxies requests to bypass CORS restrictions.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Website   │────>β”‚ Cloudflare Worker │────>β”‚ Target URL  β”‚
β”‚            β”‚     β”‚                   β”‚     β”‚             β”‚
β”‚            β”‚<────│ + CORS headers    β”‚<────│             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Security features:

  • Origin allowlist validation
  • SSRF prevention (blocks private IP ranges: 127., 10., 172.16-31., 192.168., ::1)
  • Protocol restriction (HTTP/HTTPS only)
  • Content-Type checking (HTML only)
  • Cache control headers (minimum 5 minutes)

Data Flow Summary

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Build Time                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  CMU Dictionary (126K words) ──> bundled with @ingglish/dictionaryβ”‚
β”‚  SUBTLEX Frequencies (74K) ──> bundled with @ingglish/dictionary  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Runtime                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  loadDictionary() ──> parse & cache dictionary              β”‚
β”‚  translateText() ──> O(n) word lookup + phoneme conversion  β”‚
β”‚  reverseTranslate() ──> O(1) phoneme key lookup + frequency β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

All paths are linear (no quadratic or exponential complexity). Dictionary data is loaded on-demand via dynamic imports.

See Performance for complexity tables, profiling scripts, and optimization guidelines.