AI-powered translation of UI text with per-language IndexedDB persistence, batched requests, and content filtering.
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:
The i18n system consists of five core classes in source/library/i18n/:
| Class | Role |
|---|---|
SvI18n | Singleton coordinator. Manages dedicated per-language IndexedDBs, language state, deduplicates pending promises, and exposes computed status getters (queuedCount, completedCount) for admin UI. |
SvI18nCache | Eager 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. |
SvI18nStore | Async IndexedDB bridge (i18nTranslations/store/{lang}). Purely an async read/write interface to IndexedDB with no in-memory state; promotes hits to SvI18nCache. |
SvI18nService | Batched request service. Accumulates requests for 200ms, groups by context, sends JSON templates to AI chat models, and stores results. |
SvTranslationFilter | Pluggable filter with named regex functions in a Map. Determines whether a string contains translatable linguistic content. |
SvTranslatableNode | Base class for translatable domain nodes (SvNode hierarchy). Holds per-node Tier 0 translationMap. |
When a view calls node.translatedValueOfSlotNamed("slotName"):
SvTranslatableNode checks whether translation is needed:SvI18n.shared().currentLanguage() !== "en").SvTranslationFilter.shared().shouldTranslate(text) confirms text contains linguistic content (not numbers, URLs, codes, or emails).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.SvI18n.cachedTranslate(text, context). On hit, promotes result to Tier 0 map and returns.SvI18n.asyncTranslate(text, context). On hit in i18nTranslations/store/{lang}, promotes result to Tier 1 cache and Tier 0 map, then resolves promise.SvI18nService:debounceMs), groups by context, and sends 1 AI batch JSON request.didUpdateNode() to swap UI text cleanly without flicker.SvTranslationFilter uses a pluggable Map of named filter functions to skip unnecessary API calls:
| Filter Name | Pattern Examples Skipped |
|---|---|
noAlphabetical | 17 (+3), +5 / +3 / +2, --- |
numericAndCurrency | 42, $9.99, €100, $70.16 USD, 100% |
alphanumericCodes | 23A, #7, 3d6, +5, 10/20 |
ordinals | 1st, 2nd, 3rd |
labeledNumeric | HP: 45, AC: 18, XP: 1,200 |
emailAddresses | user@example.com |
phoneNumbers | +1 (555) 123-4567 |
urlsAndIps | https://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 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" }
}
}SvNode subclass prototypes via introspection.shouldTranslate() === true.SvTranslationFilter and enqueues them for AI batch translation.// 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).SvFieldTile): Calls node.translatedValueOfSlotNamed() in visibleKey(), automatically displaying translated field labels.SvBreadCrumbsTile): Observes "svI18nLanguageChanged" notification, rebuilding breadcrumb path segments in the new language."svI18nLanguageChanged" to trigger a UI refresh when the active language changes.SvNode domain abstraction.