Production Readyv1.2.2Library • TypeScript

tstlai

Just-In-Time Web Localization Engine. tstlai (TypeScript Translation AI) is a middleware-ready library that automatically translates your web application's HTML content on the fly using AI. Unlike traditional i18n libraries that require maintaining massive JSON files, tstlai intercepts your HTML, extracts the text, and uses AI to provide context-aware translations.

Live Demo: This very site uses tstlai! Change your browser language or visit /es, /fr, /de, or any locale to see it in action. Read how we built it →

Key Features

Just-In-Time Translation

No manual translation files. Content is translated as it is rendered.

HTML-Safe

Intelligent parsing ensures your HTML structure, classes, and attributes remain untouched.

Smart Caching

SHA-256 content hashing with memory or Redis caching for production-grade performance.

AI-Powered

Pluggable AI providers (OpenAI) for high-quality, context-aware translations.

RTL Support

Automatically detects Right-to-Left languages and sets the dir="rtl" attribute.

Selective Translation

Respects data-no-translate attributes and ignores script, style, and code tags.

Streaming Translations

Watch translations appear one-by-one as they complete from the LLM with streaming support.

46 Supported Languages

Tiered language support with quality indicators. Use isLanguageSupported() to validate locales.

CLI Generate Command

Generate static translation files at build time. Translate once, deploy everywhere.

Contextual Strings

Disambiguate words like "Save", "Post", "Match" with context hints for accurate translations.

Session-Based Security

Dynamic endpoints with cryptographic tokens prevent API abuse. Each session gets a unique, unguessable path.

How It Works

tstlai uses a multi-stage workflow to translate your HTML content:

1

Parse

The engine parses incoming HTML and extracts text nodes. It automatically ignores non-content tags like script, style, and code.

2

Hash & Check

Each text segment is hashed using SHA-256. The system checks the cache for existing translations to save costs and reduce latency.

3

Translate

Cache misses are batched and sent to the AI provider in a single request for efficient translation.

4

Reconstruct

The translated text is injected back into the DOM, preserving the original layout perfectly.

Quick Start

Installation

npm install tstlai

Basic Usage

import { Tstlai } from 'tstlai';

async function main() {
  // 1. Initialize the Engine
  const translator = new Tstlai({
    targetLang: 'es', // Target language code
    provider: {
      type: 'openai',
      // apiKey, model, and baseUrl can be omitted if set via env vars:
      // OPENAI_API_KEY, OPENAI_MODEL, OPENAI_BASE_URL
    },
    cache: {
      type: 'memory',
      ttl: 3600 // Cache duration in seconds
    }
  });

  // 2. Your raw HTML content
  const rawHtml = `
    <article>
      <h1>Welcome to the Future</h1>
      <p>Translate your website instantly.</p>
      <button data-no-translate>tstlai v1.0</button>
    </article>
  `;

  // 3. Process the HTML
  const result = await translator.process(rawHtml);
  console.log(result.html);
}

main();

Output

<article>
  <h1>Bienvenido al Futuro</h1>
  <p>Traduce tu sitio web al instante.</p>
  <button data-no-translate>tstlai v1.0</button>
</article>

Framework Integration

tstlai provides first-class integrations for popular frameworks:

Express / Node.js Middleware

import express from 'express';
import { Tstlai, integrations } from 'tstlai';

const app = express();
const translator = new Tstlai({
  targetLang: 'es',
  provider: { type: 'openai' }
});

// Apply middleware
app.use(integrations.createExpressMiddleware(translator));

app.get('/', (req, res) => {
  res.send('<h1>Hello World</h1>');
  // Automatically translated to <h1>Hola Mundo</h1>
});

Next.js (App Router) - Zero Refactoring

Drop AutoTranslate into your layout and your entire app translates automatically. No changes to page components needed.

// src/lib/translator.ts
import { Tstlai } from 'tstlai';

const translators = new Map<string, Tstlai>();

export function getTranslator(locale: string): Tstlai {
  if (!translators.has(locale)) {
    translators.set(locale, new Tstlai({
      targetLang: locale,
      sourceLang: 'en',
      provider: { type: 'openai' },
      cache: { type: 'redis' } // or 'memory'
    }));
  }
  return translators.get(locale)!;
}

// src/app/api/tstlai/translate/route.ts
import { createNextRouteHandler } from 'tstlai/next';
import { getTranslator } from '@/lib/translator';

export const POST = async (req: Request) => {
  const { targetLang } = await req.json();
  const handler = createNextRouteHandler(getTranslator(targetLang));
  return handler(new Request(req.url, {
    method: 'POST',
    headers: req.headers,
    body: JSON.stringify({ targetLang }),
  }));
};

// src/app/[locale]/layout.tsx
import { AutoTranslate } from 'tstlai/next';

export default async function LocaleLayout({ children, params }) {
  const { locale } = await params;
  return (
    <>
      {children}
      {locale !== 'en' && <AutoTranslate targetLang={locale} />}
    </>
  );
}

// That's it! Your pages stay exactly as they are.
// English renders normally, other locales auto-translate.

Next.js (next-intl Compatible)

Zero-effort migration from next-intl. Use your existing en.json as the source of truth.

// src/i18n.ts
import { Tstlai, integrations } from 'tstlai';
import enMessages from '../messages/en.json';

const translator = new Tstlai({
  targetLang: 'en',
  provider: { type: 'openai' }
});

export const { getTranslations } = integrations.createNextIntlAdapter(
  translator, 
  enMessages
);

// In Server Components (just like next-intl):
import { getTranslations } from '@/i18n';

export default async function Page({ params: { locale } }) {
  const t = await getTranslations(locale);
  return <h1>{t('landing.hero.title')}</h1>;
}

Other Frameworks

Fastify

Plugin-based integration with createFastifyPlugin()

Astro

Middleware support with createAstroMiddleware()

Remix

Handler wrapper with createRemixHandler()

Client-Side

Zero-config with AutoTranslate - scans DOM and translates automatically

Configuration

Redis Caching

const translator = new Tstlai({
  // ...
  cache: {
    type: 'redis',
    connectionString: 'redis://localhost:6379',
    ttl: 86400, // 24 hours
    keyPrefix: 'tstlai:' // Default namespace
  }
});

// Multi-language cache keys: tstlai:<hash>:<lang>
// Translations for different languages are stored separately

Environment Variables

OPENAI_API_KEYYour OpenAI API key
OPENAI_MODELDefault: gpt-3.5-turbo
OPENAI_BASE_URLDefault: https://api.openai.com/v1
REDIS_URLDefault: redis://localhost:6379

Preventing Translation

Add the data-no-translate attribute to prevent specific elements from being translated:

<span data-no-translate>BrandName™</span>

CLI Generate & Contextual Strings

Generate static translation files at build time and disambiguate context-sensitive words.

CLI Generate Command

Create translation files from your source JSON at build time. Translate once, deploy everywhere.

# Generate Spanish translations from English source
npx tstlai generate --source messages/en.json --target es --output messages/es.json

# Generate multiple locales
npx tstlai generate --source messages/en.json --target es,fr,de --output messages/

Contextual Strings ($t/$ctx format)

Disambiguate words like "Save", "Post", "Match" that have different meanings in different contexts.

// In your messages/en.json
{
  "actions": {
    "save": "$t/Save/$ctx/button to store data",
    "post": "$t/Post/$ctx/publish content to feed"
  },
  "sports": {
    "match": "$t/Match/$ctx/sports competition game"
  }
}

// Or use the translateText() API with context
await translator.translateText("Save", { context: "button to store data" });
await translator.translateText("Match", { context: "sports competition" });

Language Support API

tstlai exports its language support data for use in middleware and routing.

Available Exports

SUPPORTED_LANGUAGESAll 46 supported languages
TIER_1_LANGUAGES12 high-quality languages
TIER_2_LANGUAGES21 good-quality languages
TIER_3_LANGUAGES13 functional languages
SHORT_CODE_DEFAULTSMap of short codes (en → en_US)
isLanguageSupported(code)Check if locale is supported
normalizeLocaleCode(code)Resolve short codes to full locale

Usage in Middleware

import { isLanguageSupported, SHORT_CODE_DEFAULTS } from 'tstlai';

// Use short codes for browser negotiation
const NEGOTIATION_LOCALES = Object.keys(SHORT_CODE_DEFAULTS);

// In your middleware
if (!isLanguageSupported(locale)) {
  return NextResponse.redirect(new URL('/en' + pathname, request.url));
}

Streaming Translations

Watch translations appear progressively as each one completes from the LLM.

AutoTranslate with Streaming

<AutoTranslate 
  targetLang={locale} 
  stream={true}
  streamEndpoint="/api/tstlai/stream"
  streamBuffer={500} // Buffer first 500ms for smoother initial render
/>

Streaming Route Handler

// src/app/api/tstlai/stream/route.ts
import { createNextStreamingRouteHandler } from 'tstlai/next';
import { getTranslator } from '@/lib/translator';

export const POST = async (req: Request) => {
  const { targetLang } = await req.json();
  const handler = createNextStreamingRouteHandler(getTranslator(targetLang));
  return handler(req);
};

Start Translating Your App Today

No more JSON files. No more manual translations. Just AI-powered localization that works.