Dialekt [diˈalɛkt, German for "dialect"] is a CLI toolkit that automates application string translation using large language models, regardless of your tech stack. It detects missing keys in target locales, calls an LLM to produce translations, and writes the results using framework-specific adapters.
When you ship in more than one language, your translation files drift out of sync the moment someone edits a string in the source locale. dialekt solves this by diffing your locale files against each other, sending the missing keys to an LLM, and writing the translated results back. It handles token limits by chunking large translation sets, and retries individual chunks when the model returns malformed output.
dialekt is an extendable harness, not a closed box. The core package handles chunking, retries, missing-key detection on top of an interface which allows integrations for specific file formats and i18n frameworks to be built separately. Several first-party integrations ship out of the box, and writing your own means implementing a single interface with four methods.
| Command | What it does |
|---|---|
translate |
Finds missing keys and asks the LLM to fill them |
validate |
Exits non-zero if any locale is missing keys |
add |
Inserts a new key and triggers translation |
missing |
Lists every missing key without writing files |
unused |
Scans source code for keys that no longer appear |
languages |
Shows which locales each adapter detected |
npm install -D dialekt @dialekt/adapter-laravelInstall only the adapters you use. If you also have a Paraglide frontend:
npm install -D @dialekt/adapter-paraglideCreate dialekt.config.ts in your project root:
import { defineConfig } from "dialekt";
import { laravel } from "@dialekt/adapter-laravel";
export default defineConfig({
sourceLocale: "en",
targetLocales: ["de", "fr", "es"],
model: { provider: "openai", modelId: "gpt-4o" },
chunking: { maxTokens: 3000, charsPerToken: 3.0, concurrency: 3 },
retry: { maxAttempts: 3, baseDelayMs: 1000 },
adapters: [laravel({ langDir: "./lang", scanPaths: ["./app", "./resources/views"] })],
});dialekt runs on top of the Vercel AI SDK, which means any LLM provider with an AI SDK integration works out of the box.
You can configure your model in two ways:
A — Provider + model ID (the simple way)
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 — A live Vercel AI SDK model object (for any provider or custom setup)
import { openai } from "@ai-sdk/openai";
import { createOpenAI } from "@ai-sdk/openai";
import { anthropic } from "@ai-sdk/anthropic";
// Any AI SDK factory works:
export default defineConfig({
model: openai("gpt-4o-mini"),
// or a custom OpenAI-compatible endpoint:
fastModel: createOpenAI({
baseURL: "https://your-proxy.com/v1",
apiKey: process.env.CUSTOM_KEY,
})("gpt-4o-mini"),
});This means you can use any provider from the
Vercel AI SDK providers list —
OpenAI, Anthropic, Google, Mistral, Groq, Together, Fireworks, DeepSeek,
OpenRouter, Perplexity, xAI, and dozens more. Just install the corresponding
@ai-sdk/* package and pass the model object directly.
export OPENAI_API_KEY=sk-...
# or ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEYnpx dialekt translateAn adapter teaches dialekt how to read and write your framework's translation files. Install only the ones you use.
| Adapter | File format |
|---|---|
@dialekt/adapter-laravel |
PHP array files (lang/{locale}/{domain}.php) and JSON locale files |
@dialekt/adapter-paraglide |
inlang message-format JSON (messages/{locale}.json) |
@dialekt/adapter-json |
Plain JSON locale files |
@dialekt/adapter-yaml |
YAML locale files (.yml / .yaml) |
@dialekt/adapter-xliff |
XLIFF translation files (.xlf / .xliff) |
@dialekt/adapter-po |
GNU gettext .po files |
@dialekt/adapter-android |
Android strings.xml resources |
@dialekt/adapter-ios |
iOS .strings files |
@dialekt/adapter-arb |
Flutter Application Resource Bundle (.arb) |
@dialekt/adapter-csv |
CSV locale tables |
@dialekt/adapter-properties |
Java .properties files |
The Laravel adapter requires php on your PATH. Both the Laravel and Paraglide adapters can scan your source code for stale keys: Laravel looks for __('domain.key') calls, Paraglide looks for m.messageName(...) references.
You can write your own adapter by implementing the TranslationAdapter interface. See packages/adapter-laravel/src/adapter.ts for a full example.
dialekt is written in TypeScript on top of Effect-TS. Every file read, every API call, and every parse error is either handled or reported as a typed failure. Nothing gets swallowed in a catch block. The architecture is layered:
- CLI layer (
@effect/cli) — parses flags, resolves config files, wires up the runtime - SDK layer — the public API for custom scripts:
runTranslation,resolveModel, chunking - Adapter layer — framework-specific I/O: reading locale files, writing them back, scanning source for unused keys
- Translation layer — the LLM interaction itself: prompt construction, response parsing, retry logic
The examples/ folder contains working projects you can run dialekt against without setting up your own app. cd into an example and run the commands from there.
cd examples/laravel
npx dialekt translate
npx dialekt missing
npx dialekt unusedThe Laravel example includes lang/en/auth.php, lang/en/validation.php, lang/en.json, and their German counterparts. Some keys are intentionally missing from the German files so translate and missing have something to report. The unused command scans resources/views/welcome.blade.php and app/Http/Controllers/UserController.php for __(), @lang(), and trans() calls.
cd examples/paraglide
npx dialekt translate
npx dialekt missing
npx dialekt unusedThe Paraglide example includes messages/en.json and messages/de.json with inlang message-format strings (some keys intentionally missing from German). The unused command scans src/lib/i18n.ts and src/routes/+page.svelte for m.messageName(...) calls.
Note: Both examples require an
OPENAI_API_KEY(or equivalent) in your environment. Thetranslatecommand makes real API calls. Use--fastfor cheaper runs.
pnpm install
pnpm -r run build
pnpm -r run typecheck
pnpm -r run test
pnpm exec gesetz checkMIT