docs

Everything you need to translate your website with one line of code.

Quick Start

Add this script tag to your HTML. That's it.

<script src="https://tongues.80x24.ai/t.js" data-lang="en" defer></script>

Set data-lang to your page's language. When a visitor's browser matches, auto-translate is skipped (zero API calls). When it doesn't match, tongues translates automatically. No UI injected. No build step.

Version Pinning

The script above always loads the latest version. If you need a fixed version that won't change:

<script src="https://tongues.80x24.ai/t@1.0.0.js" defer></script>

Pinned versions are cached aggressively (immutable). Upgrade by changing the version number when you're ready.

How It Works

  1. Script loads, reads navigator.language
  2. Scans DOM for translatable elements (headings, paragraphs, buttons, links, etc.)
  3. Checks localStorage cache — if hit, applies instantly
  4. Cache miss: calls tongues API, which checks Redis → SQLite → Claude AI
  5. Translated text replaces DOM content, stored in cache for next visit
  6. MutationObserver watches for new content (SPA navigation, lazy loading)

Source Language (data-lang)

Tell tongues what language your page is written in:

<script src="https://tongues.80x24.ai/t.js" data-lang="ko" defer></script>

When data-lang matches the visitor's browser locale (base language comparison — ko-KR matches ko), auto-translate is skipped entirely. Zero API calls. When the locale differs, translation runs normally.

window.t.sourceLocale returns the data-lang value. setLocale() still works for manual translation even when auto-translate is skipped.

Without data-lang, tongues auto-detects the source language via heuristic — but setting it explicitly is recommended for best results and zero-cost same-language visits.

window.t API

tongues exposes a global window.t object for programmatic control.

t.locale
Read-only. Current translation locale (e.g. "en", "ja").
t.sourceLocale
Read-only. The data-lang value if set, otherwise the detected browser locale.
t.version
Read-only. Client script version (e.g. "1.0.0").
await t.setLocale("ja")
Switch to a specific language. Returns a Promise.
t.restore()
Revert to original text.
await t.translateEl(target, options?)
Translate specific element(s). Accepts a CSS selector string, an Element, or an array of Elements. Bypasses root's translate="no" while respecting inner descendants'. Pass { to: "ko" } to translate to a specific locale without changing global state. When to matches source language, restores original text without API call.

Example: Language Switcher

// Simple language picker
const langs = ["en", "ja", "zh", "ko", "es"];

langs.forEach(lang => {
  const btn = document.createElement("button");
  btn.textContent = lang.toUpperCase();
  btn.onclick = () => window.t.setLocale(lang);
  document.getElementById("lang-picker").append(btn);
});

Manual Mode

By default, tongues auto-translates the page on load based on the visitor's browser language. If you want full control over when translation starts, add the data-manual attribute:

<script data-manual src="https://tongues.80x24.ai/t.js" defer></script>

In manual mode, tongues loads and sets up the MutationObserver, but does not translate on page load. Call t.setLocale() to trigger translation when you're ready:

// User clicks a language button
document.getElementById("lang-ko").onclick = () => {
  window.t.setLocale("ko");
};

This is useful when you need to wait for user interaction, load data first, or build a custom language picker. The window.t API works the same in both modes.

Translation Hints (preprompt)

tongues automatically reads your page's <title> and <meta name="description"> to understand context. For extra precision, add a data-preprompt attribute with a short hint (max 30 characters):

<script src="https://tongues.80x24.ai/t.js" data-preprompt="음식 메뉴 번역" defer></script>

The hint is injected into the AI's system prompt as a Note directive. This helps resolve ambiguous terms. For example:

Without data-preprompt, tongues still works — it uses page title and description for context. The preprompt adds an explicit layer for sites where domain-specific vocabulary matters.

How it combines with page metadata

All three context sources coexist in the system prompt:

  1. pageTitle — from <title> (automatic)
  2. pageDescription — from <meta name="description"> (automatic)
  3. preprompt — from data-preprompt attribute (manual, max 30 chars)

They don't replace each other. Page metadata provides implicit context, while preprompt is your explicit instruction to the translator.

Excluding Content

Prevent specific elements from being translated:

<!-- HTML5 standard -->
<span translate="no">MenuPie</span>

<!-- Google Translate convention (also works) -->
<code class="notranslate">npm install</code>

Both translate="no" and .notranslate are respected. Children of excluded elements are also skipped. Use t.translateEl() to explicitly translate excluded elements when needed.

Selective Translation

Use translate="no" to exclude elements from automatic translation. Then use t.translateEl() to translate them on demand.

translate="no"

Excludes an element and its children from all automatic translation — page load, setLocale(), and MutationObserver. Only t.translateEl() can translate it.

<nav>UI translates automatically</nav>
<main translate="no">Content stays original until you say so</main>

translateEl() and translate="no"

When you call t.translateEl(root), the root element's translate="no" is bypassed. But translate="no" on inner descendants is still respected — protecting code blocks, brand names, etc.

<main translate="no">
  <p>This gets translated by translateEl()</p>
  <pre translate="no"><code>const x = 1;</code></pre> <!-- still protected -->
</main>
// Globe button clicked → translate content
await t.translateEl("main");
// main's translate="no" bypassed, inner <pre translate="no"> protected

Pattern: UI auto + content on-demand

A common pattern is auto-translating UI while keeping content in the original language until the user explicitly switches:

<script src="https://tongues.80x24.ai/t.js" data-lang="en" defer></script>
<nav>Menu items</nav>              <!-- auto-translated on load -->
<main translate="no">Content</main>  <!-- stays original -->
// User clicks globe → translate content only (UI untouched)
async function onLanguageChange(lang) {
  await t.translateEl("main", { to: lang });
}

// Restore content to original — no API call
await t.translateEl("main", { to: t.sourceLocale });

With { to }, you don't need setLocale(). Global locale stays unchanged — only the target element is translated to the specified language.

Pattern: UI + content together

If you want both UI and content to translate together:

async function onLanguageChange(lang) {
  await t.setLocale(lang);           // translate UI
  await t.translateEl("main");       // translate content (uses current locale)
}

Use Cases

// Modal opens → translate its content
document.getElementById("modal").showModal();
await t.translateEl("#modal");

SPA Support

tongues uses a MutationObserver to detect DOM changes. When your framework (React, Svelte, Vue, etc.) adds or updates content, tongues automatically translates it.

Caching

Translations are cached at multiple layers for speed and cost efficiency:

  1. localStorage (client) — per domain, per locale. Instant on repeat visits
  2. Redis (server) — shared across all visitors, 24h TTL
  3. SQLite (server) — permanent persistent storage
  4. Claude AI — real-time translation on cache miss

Cache keys are based on the original text content. If you change the text on your site, the cache automatically invalidates — no manual purging needed.

Supported Languages

tongues uses Claude AI for translation, which supports virtually any language. Just pass any valid locale code to t.setLocale() — no predefined list required.

Pricing

Free
1,000 requests / 10,000 texts per month
Pro — $4.99/mo
50,000 requests / 500,000 texts per month
Business — $9.99/mo
500,000 requests / 5,000,000 texts per month

Register your domain and check usage on the dashboard.