Skip to content

Internationalization

Parallax Designer uses a custom typed i18n system with no external dependency (no vue-i18n). The system provides compile-time type safety for translation keys and runtime parameter interpolation.

Supported Locales

CodeLanguageCatalog File
enEnglishsrc/i18n/locales/en.ts
frFrenchsrc/i18n/locales/fr.ts

Locale Files

FilePurpose
src/i18n/config.tsSupported locale metadata, default locale, storage key
src/i18n/locales/en.tsEnglish source-of-truth catalog
src/i18n/locales/fr.tsFrench catalog
src/i18n/locales/index.tsLocale registry used by the app runtime

Runtime Behavior

Locale Detection

On startup, the locale is determined by this priority chain:

  1. localStorageparallax-designer-locale key
  2. Browser localenavigator.languages, normalized to base tag (e.g., fr-CAfr)
  3. Defaulten

Locale Persistence

  • Language changes are persisted immediately to localStorage
  • The active locale updates the <html lang> attribute via useI18n
  • Locale preference is app-level state — it is not stored in the project payload/schema

Translation API

The useI18n composable exposes:

Method / PropertyDescription
localeReadonly reactive ref to the active locale code
setLocale(code)Switch to a specific locale
toggleLocale()Cycle to the next supported locale
t(key, params?)Typed translation lookup with {name} parameter interpolation
getHelp(helpKey)Retrieve localized help panel content for a given control key
formatDateTime(epochMs, options?)Locale-aware date/time formatting

Type Safety

Translation keys are fully type-safe. The TranslationKey type is derived from the English catalog structure via a recursive LeafPaths<T> utility type that extracts all dot-separated paths to leaf string values.

ts
// If the catalog has:
// { scene: { maxRot: { label: "Max Rotation" } } }
// Then valid keys include: "scene.maxRot.label"

Using an invalid key in t() produces a TypeScript compile error.

Parameter Interpolation

Translations can include {name} placeholders:

ts
// Catalog: "Layer limit reached ({maxLayers})"
t("layers.limitReached", { maxLayers: 30 });
// → "Layer limit reached (30)"

Catalog Rules

  • Keep all keys identical across all locale files (mirror the en.ts structure exactly)
  • Keep placeholders exactly the same ({count}, {name}, etc.)
  • Project payload/schema values are language-neutral — only UI copy is localized
  • Translate the full UI surface: labels, tooltips, help content, dialogs, toasts, placeholders, and ARIA text

Build-Time Validation

The check:i18n script (scripts/check-i18n.mjs) validates key parity between English and all other locales at build time:

bash
npm run check:i18n

The script:

  1. Uses the TypeScript compiler API to transpile each locale .ts file to CommonJS
  2. Runs the transpiled code in a Node vm sandbox to extract the catalog object
  3. Extracts all leaf paths from each catalog
  4. Compares every locale's leaf paths against the English catalog
  5. Reports any missing or extra keys

This runs automatically as part of the npm run check pipeline.

Adding a New Locale

  1. Register the locale in src/i18n/config.ts — add the locale code and display metadata
  2. Create the catalog — Copy src/i18n/locales/en.ts to src/i18n/locales/<code>.ts, export a <CODE>_LOCALE constant, and translate all values
  3. Register the export in src/i18n/locales/index.ts — import and add to the locale map
  4. Validate:
    bash
    npm run check:i18n   # Verify key parity
    npm run typecheck    # Ensure typed key usage stays valid
    npm run build        # Build app assets

Parallax Designer Documentation

Scroll to zoom · Drag to pan