llm cli · application translation
dialekt.
dialekt is a command-line tool that translates application strings with a large language model. It finds the keys that are missing from your target locale files, sends them to a model, and writes the translations back in the file format that your framework uses.
## what it does
When you add or edit a string in your source locale, the other locale files go out of sync. dialekt diffs every target locale against your source, detects the missing keys, and fills them with model-generated translations. It chunks large translation sets to stay under token limits, retries a chunk when the model returns malformed output, and writes the results back through an adapter for your framework. It does not touch keys that already exist.
## the translation loop
Running dialekt translate puts every target
locale through the same pipeline: diff it against the source, split the missing keys into chunks,
send each chunk to the model, validate the response, and write the translations back through your
framework's adapter. Chunks run concurrently, and a chunk that fails validation is retried with
exponential backoff instead of aborting the run.
## commands
translate
Finds missing keys, chunks them, calls the model, and writes the results.
add
Inserts a new key in the source and translates it to every target locale.
missing
Lists every missing key without writing any files.
unused
Scans your source code and flags keys that nothing references.
validate
Exits with a non-zero code when any locale is missing keys, for CI.
languages
Prints the locales that each adapter detected.
## frameworks
dialekt reads and writes your translation files through an adapter. An adapter knows how to parse your framework's locale files, find the keys, and write the translations back.
## supported adapters
laravel
PHP array files (lang/{locale}/{domain}.php) and JSON locale files.
paraglide
Inlang message-format JSON (messages/{locale}.json).
json
Plain JSON locale files.
yaml
YAML locale files (.yml / .yaml).
xliff
XLIFF translation files (.xlf / .xliff).
po
GNU gettext .po files.
android
Android strings.xml resources.
ios
iOS .strings files.
arb
Flutter Application Resource Bundle (.arb).
csv
CSV locale tables.
properties
Java .properties files.
You can write an adapter for another framework by implementing one interface with four methods: listLocales, read, write, and findUsedKeys. See write your own adapter below.
## model providers
dialekt is built on the Vercel AI SDK, so any LLM provider with an AI SDK integration works. Configure a model in one of two ways:
A — provider + model id
model: { provider: "openai", modelId: "gpt-4o" },
model: { provider: "openrouter", modelId: "deepseek/deepseek-v4-flash" },
model: { provider: "anthropic", modelId: "claude-sonnet-4-20250514" },
model: { provider: "google", modelId: "gemini-2.5-flash" },
B — live Vercel AI SDK model
import { openai } from "@ai-sdk/openai";
import { createOpenAI } from "@ai-sdk/openai";
// any AI SDK factory works
export default defineConfig({
model: openai("gpt-4o-mini"),
// or bring your own OpenAIcompatible endpoint
fastModel: createOpenAI({ baseURL: "https://your-proxy.com/v1" })("gpt-4o-mini"),
});
This means you can use providers like OpenAI, Anthropic, Google, Mistral, Groq,
Together, Fireworks, DeepSeek, OpenRouter, Perplexity, xAI, and
dozens more —
just install the matching @ai-sdk/* package and pass the model.
## get started
1. install
npm install -D dialekt @dialekt/adapter-laravel
2. set an API key
dialekt gets its models through OpenRouter, so one key covers every provider.
Put it in a .env file in your project root.
OPENROUTER_API_KEY=sk-or-...
3. configure
Create dialekt.config.ts in your project root. Point an adapter at your
locale files, and load the key with env.
import { defineConfig } from "dialekt";
import { laravel } from "@dialekt/adapter-laravel";
export default defineConfig({
env: [".env"],
sourceLocale: "en",
targetLocales: ["de", "fr", "es"],
model: { provider: "openrouter", modelId: "anthropic/claude-opus-4" },
adapters: [
laravel({ langDir: "./lang", scanPaths: ["./app", "./resources/views"] }),
],
});
4. translate
npx dialekt translate
To use a different model, change modelId to any model OpenRouter lists —
for example openai/gpt-4o or google/gemini-2.0-flash.
You can also point a command at a second config with
--config path/to/other.config.ts.
## write your own adapter
An adapter teaches dialekt how to read and write your framework's translation files.
Implement the TranslationAdapter interface — four methods:
listLocales()
Return the locale codes that the adapter finds on disk.
read(locale)
Return all keys and their strings for a locale.
write(locale, entries)
Write translated keys back to the locale's files.
findUsedKeys()
Scan source code and return the keys that are referenced.
dialekt handles the rest — the diffing, chunking, retries, and model calls. The adapter only knows about files.
import type { TranslationAdapter } from "dialekt";
export function myFramework(): TranslationAdapter {
return {
name: "my-framework",
async listLocales() {
// read your locale directory, return ["en", "de", ...]
},
async read(locale) {
// parse the locale's files, return a flat key → string map
},
async write(locale, entries) {
// write the translated keys back in your format
},
async findUsedKeys() {
// scan your source for translation calls, return the keys
},
};
}
Register it in your config's adapters array and dialekt treats it
like a first-party adapter. See
packages/adapter-laravel/src/adapter.ts for a full reference.