Skip to content
sigilcoPublic

About

AI-powered i18n translation plugin for all bundlers

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

intl-ai

AI-powered i18n translation, shipped as a single binary

npm CI License: Apache-2.0 GitHub stars

Documentation · Roadmap · Discussions · Report an issue

intl-ai translates your locale files with any AI provider, at build time or on demand. One Rust binary, no Node dependency, no runtime code. A lockfile tracks per-key provenance and review state, so AI output never silently overwrites human work.

intl-ai demo

Why intl-ai

Most i18n translation workflows are manual (copy JSON, open a translation tool, paste back) or runtime-heavy (call an AI API on every page load). intl-ai runs at build time so translations are baked in before your app ships.

  • Zero runtime overhead. Translations happen during the build, not in the browser or on the server.
  • Any stack. The binary reads and writes locale_dir/{locale}.json|yaml files, so it pairs with i18next, next-intl, vue-i18n, react-intl, Paraglide, and anything else that consumes flat locale files.
  • Any AI provider. An OpenAI-compatible HTTP endpoint, or a local agent CLI (claude-code, opencode, codex, crush, gemini) for keyless dev.
  • Lockfile-tracked origins. intl-ai.lock.d/ records whether each translation was written by a human or generated by AI, plus a review bit, so you always know what to trust.
  • Additive by default. fill writes missing keys only. Existing values (human or AI) are never touched unless you pass --stale, --regenerate, or --include-human.
  • ICU MessageFormat, hardline. Generated output is always ICU MessageFormat ({name}, plural/select/selectordinal, #): that constraint is what makes machine validation of AI output possible. Other placeholder syntaxes are out of scope.
  • Shift-left validation. fill --validate re-prompts the provider with check feedback until output is ICU-clean; check fails CI on missing, stale, or invalid translations.

Install

Shell (Linux, macOS, Windows/WSL)

curl -fsSL https://intl-ai.illo.fyi/install.sh | bash

PowerShell (Windows)

irm https://github.com/sigilco/intl-ai/releases/latest/download/intl-ai-installer.ps1 | iex

Homebrew

brew install sigilco/tap-intl-ai/intl-ai

mise

mise use npm:intl-ai@latest

npm / npx

npm install -g intl-ai
npx intl-ai --help

Integrations

The binary is the core. These scoped packages are thin shims that drive it from your build tool, so integration is drop-in:

Package Stack What it does
@intl-ai/unplugin Vite, Webpack, Rollup, esbuild, Rspack, Farm Runs intl-ai fill on build start and check as a CI gate
@intl-ai/next Next.js (webpack and Turbopack) withIntlAi() config wrapper; same fill/check wiring
@intl-ai/expo Expo / React Native Config plugin that runs intl-ai fill during prebuild

Each shim installs intl-ai as a dependency and exposes the same quality controls as the CLI (fill validation, judge threshold, --fail-on severities) as plugin options. For stacks without a shim (Flutter, Xcode/SwiftPM, Gradle, MSBuild, generic npm scripts), run the binary directly in the lifecycle hook your stack provides; see the per-stack recipes in the docs.

Community integrations

The packages above are tier-1: maintained in this repo and versioned in lockstep with the binary. Integrations for other stacks (a Flutter plugin, a Gradle task, an Xcode build phase, a Metro wrapper) are community-supported: owned by their authors, listed in the docs. If you build one, the community integrations guide covers the shim contract (resolve the binary, spawn at the right lifecycle, expose the quality controls) and how to get listed.

Quick start

intl-ai init          # writes intl-ai.toml + a replay cassette
# edit intl-ai.toml: set locale_dir, source, targets, provider
intl-ai fill          # translate missing keys
intl-ai check         # audit: missing, stale, invalid, unreviewed

A minimal config:

locale_dir = "locales"
source = "en"
targets = ["fr", "de"]

[provider]
kind = "http"
model = "your-model"
api_key = "${env:OPENAI_API_KEY}"

Or go keyless with a local agent CLI:

[provider]
kind = "command"
agent = "claude-code"

Commands

Command What it does
intl-ai init Scaffold intl-ai.toml and a replay cassette
intl-ai fill Translate missing keys (additive by default)
intl-ai check Read-only audit: missing, stale, invalid, modified, extra, unreviewed
intl-ai status Per-locale inventory counts
intl-ai mark <keys> --origin ai|human Set key provenance (or --absent for tombstones)
intl-ai review / unreview Set or clear the review bit on keys
intl-ai lockfile check|fmt|merge Validate, normalize, or merge lockfile shards
intl-ai config validate|schema Validate a config file or emit the JSON Schema

Every command accepts --format json for agent and CI consumption.

Configuration

intl-ai reads intl-ai.toml, intl-ai.json, intl-ai.yaml, or intl-ai.yml, discovered by walking ancestors to the .git boundary. Override with --config PATH or --config - (TOML on stdin).

  • Provider kinds: http (OpenAI-compatible chat completions), command (local agent CLI preset or free-form command), replay (deterministic cassette for tests).
  • ${env:VAR} and ${file:PATH} interpolation, extends for shared base config, INTL_AI_* env overlay.
  • intl-ai config validate checks a config file; intl-ai config schema emits the JSON Schema (also on SchemaStore) for editor autocomplete.

See Configuration for the full schema.

Lockfile and review workflow

intl-ai.lock.d/<locale>.toml holds one sorted TOML block per key: source hash, written value, origin (ai or human), and reviewed. Commit it — it is a text format designed for git diffs and merges (intl-ai lockfile merge resolves conflicts union-style, human wins).

  • A value that differs from what AI last wrote counts as human-owned: fill will not touch it, and a stale source marks it as a check finding, never an auto-rewrite.
  • intl-ai review / unreview manage the review bit; check --fail-on unreviewed is the human-in-the-loop gate for CI.

CI

intl-ai check --fail-on missing,stale,invalid exits 10 when findings fire and prints a JSON report under --format json. Run it after fill (or standalone) in your pipeline.

Migration

Coming from the 0.4.x @intl-ai/* npm packages:

  1. Install the binary (see Install above). If you used @intl-ai/unplugin or @intl-ai/next, upgrade to the new major version instead of dropping the dependency: the scoped packages are now thin shims that run the binary for you.
  2. Rename intl-ai.config.ts / .json to intl-ai.toml (config keys are now snake_case: api_key, locale_dir, source/targets instead of defaultLocale/locales).
  3. Delete intl-ai.lock.json and run intl-ai fill once: existing keys are recorded as human-owned (never overwritten) and fresh intl-ai.lock.d/ shards are written. If you want the 0.4.x provenance imported instead, do it by hand or hand the migration guide to an agent.
  4. --force is gone: use fill --stale (AI-owned stale keys) or fill --regenerate (all AI-owned keys); --include-human additionally covers human-owned values.

The TypeScript implementation is frozen on the legacy branch. @intl-ai/api and @intl-ai/cli stay deprecated; @intl-ai/unplugin, @intl-ai/next, and @intl-ai/expo are re-released as binary-driven shims.

License

Apache-2.0

About

AI-powered i18n translation plugin for all bundlers

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages