or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli-tools.mdcore-localization.mdindex.mdmessage-processing.mdruntime-translation.mdtranslation-files.md
tile.json

runtime-translation.mddocs/

Runtime Translation

Functions for loading and managing translations at runtime, enabling dynamic language switching and translation loading without requiring build-time compilation.

Capabilities

Load Translations

Loads translations for use by $localize when doing runtime translation.

/**
 * Load translations for use by $localize at runtime.
 * Loading new translations overwrites previous ones with same MessageId.
 * Messages are only processed once when first encountered.
 * 
 * @param translations - Map from message ID to translated message string
 */
function loadTranslations(translations: Record<MessageId, TargetMessage>): void;

type MessageId = string;
type TargetMessage = string;

Usage Examples:

import { loadTranslations } from "@angular/localize";

// Load Spanish translations
loadTranslations({
  "4286451273117902052": "¡Hola, Mundo!",
  "2788806693285683417": "¡Hola, {$PH}!",
  "1234567890123456789": "Hay {$itemCount} elementos para {$userName}."
});

// Load from external source
async function loadSpanishTranslations() {
  const response = await fetch('/translations/es.json');
  const translations = await response.json();
  loadTranslations(translations);
}

// Overwrite existing translation
loadTranslations({
  "4286451273117902052": "¡Saludos, Mundo!" // Overwrites previous
});

Clear Translations

Removes all translations that were loaded using loadTranslations().

/**
 * Remove all translations for $localize.
 * Clears all translations loaded into memory and resets translate function.
 */
function clearTranslations(): void;

Usage Examples:

import { clearTranslations } from "@angular/localize";

// Clear all loaded translations
clearTranslations();

// Switch languages by clearing and reloading
function switchLanguage(locale: string) {
  clearTranslations();
  return loadTranslationsForLocale(locale);
}

Internal Translation Function

The internal translation function that processes messages using loaded translations.

/**
 * Translate message parts and substitutions using loaded translations.
 * Reorders substitutions as indicated in matching translation.
 * Warns on missing translations and returns original on error.
 * 
 * @param messageParts - Template string array parts
 * @param substitutions - Substitution values
 * @returns Tuple with translated parts and reordered substitutions
 */
function translate(
  messageParts: TemplateStringsArray,
  substitutions: readonly any[]
): [TemplateStringsArray, readonly any[]];

Translation Format

Message ID Format

Message IDs are computed hashes that uniquely identify translatable strings:

// Source: $localize`Hello, World!`
// Message ID: "4286451273117902052"

// Source: $localize`Hello, ${name}!`  
// Message ID: "2788806693285683417"

Translation String Format

Translations use {$PLACEHOLDER_NAME} syntax for placeholders:

{
  // Simple message
  "4286451273117902052": "¡Hola, Mundo!",
  
  // With placeholder
  "2788806693285683417": "¡Hola, {$PH}!",
  
  // With named placeholders
  "1234567890123456789": "Hay {$itemCount} elementos para {$userName}.",
  
  // HTML with placeholders (from Angular templates)
  "5555555555555555555": "pre{$START_TAG_SPAN}inner-pre{$START_BOLD_TEXT}bold{$CLOSE_BOLD_TEXT}inner-post{$CLOSE_TAG_SPAN}post"
}

Template Integration

Angular templates with i18n attributes generate $localize calls:

<!-- Template -->
<div i18n>pre<span>inner-pre<b>bold</b>inner-post</span>post</div>

<!-- Compiled to -->
ɵɵi18n(1, $localize`pre{$START_TAG_SPAN}inner-pre{$START_BOLD_TEXT}bold{$CLOSE_BOLD_TEXT}inner-post{$CLOSE_TAG_SPAN}post`);

Runtime Translation Workflow

Basic Setup

import { loadTranslations } from "@angular/localize";
import "@angular/localize/init";

// 1. Load translations for target locale
loadTranslations({
  "4286451273117902052": "¡Hola, Mundo!",
  "2788806693285683417": "¡Hola, {$PH}!"
});

// 2. Use $localize normally
const greeting = $localize`Hello, World!`;
console.log(greeting); // "¡Hola, Mundo!"

const personal = $localize`Hello, ${name}!`;
console.log(personal); // "¡Hola, Alice!"

Language Switching

import { loadTranslations, clearTranslations } from "@angular/localize";

async function setLanguage(locale: string) {
  // Clear existing translations
  clearTranslations();
  
  // Load new translations
  const translations = await fetchTranslations(locale);
  loadTranslations(translations);
  
  // All subsequent $localize calls use new translations
}

async function fetchTranslations(locale: string) {
  const response = await fetch(`/translations/${locale}.json`);
  return response.json();
}

// Switch to Spanish
await setLanguage('es');
console.log($localize`Hello, World!`); // "¡Hola, Mundo!"

// Switch to French  
await setLanguage('fr');
console.log($localize`Hello, World!`); // "Bonjour, le monde!"

Error Handling

import { loadTranslations } from "@angular/localize";

// Missing translation handling
loadTranslations({
  // Only some translations provided
  "4286451273117902052": "¡Hola, Mundo!"
  // "2788806693285683417" missing
});

// Missing translation logs warning and returns original
const missing = $localize`Hello, ${name}!`;
// Console: "No translation found for..."
// Returns: "Hello, Alice!"

Integration with Build Tools

Development vs Production

// Development: runtime translations for quick iteration
if (process.env.NODE_ENV === 'development') {
  loadTranslations(require('./translations/es.json'));
}

// Production: compile-time replacement (no runtime cost)
// $localize calls replaced by build tools

Lazy Loading

class TranslationService {
  private loaded = new Set<string>();
  
  async loadLanguage(locale: string) {
    if (this.loaded.has(locale)) return;
    
    const translations = await import(`./translations/${locale}.json`);
    loadTranslations(translations.default);
    this.loaded.add(locale);
  }
}