Internationalization

← Documentation
STRVCT

AI-powered translation of UI text with per-language IndexedDB persistence, batched requests, and content filtering.

Overview

STRVCT includes a built-in internationalization (i18n) system that translates UI strings on the fly using AI language models. Rather than maintaining static, hand-edited translation files for each language, the framework sends batched translation requests to an AI service and caches the results persistently in per-language IndexedDB databases.

This approach is uniquely enabled by the naked objects pattern. Because the framework generates the UI from model slot annotations, there is a single point—the model-to-view boundary—where all display text passes through. Translation is injected at that boundary, making every model class translatable by default with no per-component wiring. In a bespoke-view framework, every component would need explicit t() calls and separate translation key files.

The system is designed around three core principles:

  • Non-blocking: Translations happen asynchronously. The UI displays English text immediately and swaps in the translated version when it arrives, with no visible delay on subsequent visits thanks to persistent caching.
  • Smart filtering: Numbers, currency amounts, codes, URLs, emails, and other non-linguistic content are detected and skipped automatically, avoiding unnecessary API calls.
  • Batched and deduplicated: Individual translation requests are debounced, grouped by context, and sent as a single batch to minimize API usage.
Model Display Text title, subtitle, slot labels Model-to-View Boundary Single point where all UI text passes through; translation hook applies automatically SvTranslationFilter & Tier 0 Map Filters non-linguistic content (URLs, numbers); checks per-node translationMap (sync O(1)) SvI18nCache (Per-Language IndexedDB) In-memory Map loaded at boot on language select; returns immediately on cache hit SvI18nService AI Translation Groups requests by context, debounces 200ms, sends single batch call; stores result UI shows source English text immediately, then swaps in translated string when promise resolves.

Core Architecture & Classes

The i18n system consists of five core classes in source/library/i18n/:

ClassRole
SvI18nSingleton coordinator. Manages dedicated per-language IndexedDBs, language state, deduplicates pending promises, and exposes computed status getters (queuedCount, completedCount) for admin UI.
SvI18nCacheEager in-memory cache. Owns i18nTranslations/cache/{lang} IndexedDB. Loads all language entries into a Map on language selection. Handles seed entries (permanent) and runtime additions with FIFO eviction.
SvI18nStoreAsync IndexedDB bridge (i18nTranslations/store/{lang}). Purely an async read/write interface to IndexedDB with no in-memory state; promotes hits to SvI18nCache.
SvI18nServiceBatched request service. Accumulates requests for 200ms, groups by context, sends JSON templates to AI chat models, and stores results.
SvTranslationFilterPluggable filter with named regex functions in a Map. Determines whether a string contains translatable linguistic content.
SvTranslatableNodeBase class for translatable domain nodes (SvNode hierarchy). Holds per-node Tier 0 translationMap.

The 4-Tier Lookup Pipeline

When a view calls node.translatedValueOfSlotNamed("slotName"):

  1. Request & Filter Verification: SvTranslatableNode checks whether translation is needed:
    • System is enabled and language is not English (SvI18n.shared().currentLanguage() !== "en").
    • Text is 20 words or fewer for slot values.
    • SvTranslationFilter.shared().shouldTranslate(text) confirms text contains linguistic content (not numbers, URLs, codes, or emails).
  2. Tier 0: Node Map (Sync $O(1)$): Checks node.translationMap (per-node FIFO Map capped at 10 items). Auto-clears lazily if language has changed since last access. On hit, returns immediately with no UI flicker.
  3. Tier 1: SvI18nCache Map (Sync $O(1)$): Checks SvI18n.cachedTranslate(text, context). On hit, promotes result to Tier 0 map and returns.
  4. Tier 2: SvI18nStore IndexedDB (Async): Calls SvI18n.asyncTranslate(text, context). On hit in i18nTranslations/store/{lang}, promotes result to Tier 1 cache and Tier 0 map, then resolves promise.
  5. Tier 3: AI Batch Translation: On complete miss, enqueues text in SvI18nService:
    • Returns English source text as immediate fallback.
    • Deduplicates: if key is pending, caller promise chains onto existing request.
    • Accumulates requests for 200ms (configurable debounceMs), groups by context, and sends 1 AI batch JSON request.
    • Stores response in Tier 1 cache and Tier 2 store, resolves pending promises, and calls didUpdateNode() to swap UI text cleanly without flicker.

Smart Non-Linguistic Filtering (`SvTranslationFilter`)

SvTranslationFilter uses a pluggable Map of named filter functions to skip unnecessary API calls:

Filter NamePattern Examples Skipped
noAlphabetical17 (+3), +5 / +3 / +2, ---
numericAndCurrency42, $9.99, €100, $70.16 USD, 100%
alphanumericCodes23A, #7, 3d6, +5, 10/20
ordinals1st, 2nd, 3rd
labeledNumericHP: 45, AC: 18, XP: 1,200
emailAddressesuser@example.com
phoneNumbers+1 (555) 123-4567
urlsAndIpshttps://example.com, 192.168.1.1

Custom domain filters can be registered dynamically:

SvTranslationFilter.shared().addFilter("diceNotation", s => /^\d*d\d+(\s*[+-]\s*\d+)?$/i.test(s));

Seed Generation & Cloud Storage Workflow

Seed files provide instant, cold-start translations. They group entries by context:

{
    "meta": { "language": "es", "entryCount": 150 },
    "entries": {
        "ui-label": { "Hit Points": "Puntos de Golpe" },
        "game-mechanic": { "Saving Throw": "Tirada de Salvacion" }
    }
}

3-Phase Seed Generation Pipeline (Admin UI):

  1. Phase 1 — Introspection (Init Seed):
    • Clears cache for current language.
    • Walks all SvNode subclass prototypes via introspection.
    • Collects labels, placeholders, valid values, and default strings for slots with shouldTranslate() === true.
    • Filters collected strings through SvTranslationFilter and enqueues them for AI batch translation.
  2. Phase 2 — Runtime Accumulation:
    • Developers browse the UI to trigger translations for dynamic strings not discoverable via static introspection (computed titles, subtitles, dynamic action labels).
  3. Phase 3 — Cloud Upload (Store Current Seed):
    • Exports all cache entries for the language, strips timestamps (marking entries as permanent seed entries), and uploads the JSON seed file to Firebase Storage.

Configuration & Tuning Parameters

// Change active language (ISO 639-1)
SvI18n.shared().setCurrentLanguage("es");

// Enable or disable translation system
SvI18n.shared().setIsEnabled(true);

SvI18nService Tuning Parameters:

  • debounceMs: Milliseconds to accumulate requests before sending batch (default: 200).
  • maxBatchSize: Maximum strings per API request (default: 50).
  • maxConcurrent: Maximum simultaneous API requests (default: 3).

View Integration Details

  • Field Tiles (SvFieldTile): Calls node.translatedValueOfSlotNamed() in visibleKey(), automatically displaying translated field labels.
  • Breadcrumb Navigation (SvBreadCrumbsTile): Observes "svI18nLanguageChanged" notification, rebuilding breadcrumb path segments in the new language.
  • Custom Views: Any view can observe "svI18nLanguageChanged" to trigger a UI refresh when the active language changes.
  • Nodes: Core SvNode domain abstraction.
  • Slots: Complete guide to slot metadata annotations.
  • AI Services: AI service provider infrastructure.