lokit — Localization Kit
lokit is a universal localization manager with AI-powered translation. It supports gettext PO, po4a documentation, i18next JSON, vue-i18n JSON, Android strings.xml, YAML, Markdown, Java .properties, Flutter ARB, JS-KV, desktop entries, and polkit policy files configured via lokit.yaml.
Features
- Config-first workflow —
lokit.yaml is required and acts as the single source of truth
- Multi-target support — one config can define many translation targets across different formats
- AI translation — 7 providers including free GitHub Copilot and Gemini
- Translation statistics — per-target progress tracking
- Smart PO management — extract, merge, update with
xgettext and msgmerge
- Native OAuth — GitHub Copilot (device code) and Gemini (browser)
- Parallel translation — concurrent API requests with configurable chunking
| Format |
Extension |
Use case |
| gettext |
.po / .pot |
Source code strings (shell, Python, C, Go) |
| po4a |
.po + po4a.cfg |
Documentation / manpages |
| i18next |
.json |
Web apps with i18next |
| vue-i18n |
.json |
Vue apps with nested JSON locales |
| android |
strings.xml |
Android resource files |
| yaml |
.yaml / .yml |
YAML key-value translations |
| markdown |
.md |
Markdown document translation |
| properties |
.properties |
Java application translations |
| flutter |
.arb |
Flutter Application Resource Bundle |
| js-kv |
.js |
JavaScript assignment key-value translations |
| desktop |
.desktop |
freedesktop desktop entry translations |
| polkit |
.policy |
PolicyKit XML policy translations |
Supported AI Providers
| Provider |
Auth |
Free tier |
| GitHub Copilot |
OAuth (device code) |
✅ with GitHub account |
| Gemini Code Assist |
OAuth (browser) |
✅ 60 req/min |
| Google AI (Gemini) |
API key |
✅ limited |
| Groq |
API key |
✅ limited |
| OpenCode |
API key (optional) |
✅ free models available |
| Ollama |
none (local) |
✅ |
| Custom OpenAI |
API key |
depends |
Installation
One-line installer (recommended)
curl -fsSL https://raw.githubusercontent.com/minios-linux/lokit/refs/heads/master/install.sh | bash
From source
git clone https://github.com/minios-linux/lokit.git
cd lokit
make build
Using go install
go install github.com/minios-linux/lokit@latest
Check version
lokit version
Quick Start
Minimal project (lokit.yaml required)
Create lokit.yaml:
source_lang: en
languages: [ru, de]
targets:
- name: app
format: i18next
dir: public/translations
pattern: "{lang}.json"
# Check project structure
lokit status
# Extract strings and create PO files
lokit init
# Authenticate
lokit auth login --provider copilot
# Translate all languages
lokit translate --provider copilot --model gpt-4.1
Multi-target project (lokit.yaml)
Create a lokit.yaml in the project root:
languages: [de, es, fr, ru]
source_lang: en
targets:
- name: app
format: gettext
dir: po
- name: docs
format: po4a
root: manpages
config: po4a.cfg
- name: website
format: i18next
root: submodules/site
dir: public/translations
languages: [de, es, fr, pt-BR, ru]
- name: mobile
format: flutter
dir: lib/l10n
Then:
lokit status # Shows all targets with stats
lokit translate --provider copilot --model gpt-4o # Translates everything
Configuration File (lokit.yaml)
lokit.yaml is required. lokit uses it as the sole source of truth.
Schema
A JSON Schema is available for editor autocompletion and validation.
To enable it in VS Code, add to the top of your lokit.yaml:
# yaml-language-server: $schema=./lokit.schema.json
Reference:
# Default languages for all targets
languages: [de, es, fr, id, it, pt, pt-BR, ru]
# Source language (default: en)
source_lang: en
# Optional default provider for `lokit translate`
provider:
id: copilot
model: gpt-4o
# base_url is supported only for custom-openai and ollama
# base_url: http://localhost:11434
# prompt: "Translate to {{targetLang}} with concise style."
# settings:
# temperature: 0.3
# Translation targets
targets:
- name: my-app # Display name (required)
format: gettext # Format (required, see below)
root: . # Working directory relative to config (default: .)
# --- gettext options ---
dir: po # Base directory for this target (required)
pot: messages.pot # POT template filename in dir (required)
sources: [src/**/*.sh] # Source globs for xgettext
keywords: [_, N_, gettext] # xgettext keywords
# --- po4a options ---
config: po4a.cfg # po4a config path relative to root
# --- i18next / vue-i18n options ---
dir: public/translations # JSON directory
pattern: "{lang}/common.json" # Required per-language file layout
# --- android options ---
dir: app/src/main/res # Android res/ directory
# --- yaml / properties / flutter / js-kv options ---
dir: translations # Files directory
pattern: "locale_{lang}.yaml" # Required for yaml/properties/flutter/js-kv
# --- markdown options ---
dir: docs/translations # Files stored under dir/LANG/
# --- overrides ---
languages: [de, es, fr] # Override global language list
source_lang: en # Override source language
prompt: "Custom prompt" # Override system prompt for AI
gettext — For code translation (shell, Python, C, Go). Reads .pot templates, translates to .po files.
po4a — For documentation (manpages, AsciiDoc). Works with po4a.cfg and its PO directory.
i18next — Flat JSON key/value translations with optional _meta and translations sections.
vue-i18n — For Vue applications with nested JSON locale files (for example buttons.save: "Save" in JSON object form).
android — For Android applications. Translates strings.xml resource files.
yaml — For YAML key-value translation files. Define pattern (example: {lang}.yaml).
markdown — For Markdown document translation. Files organized as dir/LANG/file.md.
properties — For Java .properties files. Define pattern (example: messages_{lang}.properties).
flutter — For Flutter ARB files. Define pattern (example: app_{lang}.arb).
js-kv — JavaScript key/value files (for example window.i18n = { ... }). Define pattern (example: {lang}.js).
desktop — freedesktop .desktop files with per-language fields in one file.
polkit — PolicyKit .policy XML files with per-language localized tags in one file.
Custom file layouts with pattern
For file-per-language targets (i18next, vue-i18n, yaml, properties, flutter, js-kv),
you must define pattern.
pattern is relative to dir
- it must contain
{lang}
- examples:
{lang}.json, {lang}/common.json, locale_{lang}.properties, app_{lang}.arb
targets:
- name: frontend
format: i18next
dir: frontend/src/i18n
pattern: "{lang}/common.json"
- name: java
format: properties
dir: src/main/resources/i18n
pattern: "messages_{lang}.properties"
Commands
lokit status
Shows project info and translation statistics for targets defined in lokit.yaml.
lokit status # Current directory
lokit status --root ./my-project # Specific project
lokit init
Extracts translatable strings and creates/updates translation files:
lokit init # All languages
lokit init --lang ru,de # Specific languages
- Runs
xgettext for gettext projects
- Runs
po4a --no-translations for po4a projects
- Creates missing language files for i18next, vue-i18n, yaml, properties, flutter, js-kv
- Idempotent — safe to run repeatedly
lokit translate
Translates using AI:
lokit translate --provider copilot --model gpt-4o
# All flags:
--provider string AI provider (or set provider.id in lokit.yaml)
--model string Model name (or set provider.model in lokit.yaml)
--lang, -l string Languages (comma-separated, default: all untranslated)
--parallel[=N] Enable parallel translation (default workers: 3)
--chunk int Entries per API request (0 = all at once)
--all, -a Translate all entries, including already translated ones
--fuzzy Translate fuzzy entries (default: true)
--dry-run Show what would be translated
--force, -f Ignore lock file, re-translate all entries
--prompt string Custom system prompt ({{targetLang}} placeholder)
--proxy string HTTP/HTTPS proxy URL
--api-key string API key (or provider env var)
--base-url string Custom API endpoint
--timeout duration Request timeout (0 = provider default)
--retries int Retries on rate limit (default: 3)
--delay duration Delay between translation requests
--verbose, -v Detailed logging
lokit auth
Manage provider credentials:
# Interactive login
lokit auth login
# Specific provider
lokit auth login --provider copilot
lokit auth login --provider google
# List stored credentials
lokit auth list
# Remove credentials
lokit auth logout --provider copilot
lokit auth logout # Remove all
lokit version
Show version, commit hash, and build date.
Examples
Translate a monorepo with submodules
# lokit.yaml
languages: [de, es, fr, id, it, pt, pt-BR, ru]
targets:
- name: scripts
format: gettext
dir: po
pot: messages.pot
- name: manpages
format: po4a
root: manpages
config: po4a.cfg
- name: cli-tool
format: gettext
root: submodules/my-tool
dir: po
pot: messages.pot
lokit translate --provider copilot --model gpt-4o --parallel=10
Flutter application
# lokit.yaml
languages: [de, es, fr, ru, ja, zh]
source_lang: en
targets:
- name: app
format: flutter
dir: lib/l10n
pattern: app_{lang}.arb
lokit init
lokit translate --provider copilot --model gpt-4o
Java application with .properties
# lokit.yaml
languages: [de, es, fr, ru]
source_lang: en
targets:
- name: app
format: properties
dir: src/main/resources
pattern: messages_{lang}.properties
Parallel translation with proxy
lokit translate \
--provider copilot --model gpt-4.1 \
--parallel=10 --chunk 50 \
--proxy "http://proxy:8080"
Translate specific languages
lokit translate --provider copilot --model gpt-4o --lang ru,de
Use local Ollama
lokit translate --provider ollama --model llama3
Custom OpenAI endpoint
lokit auth login --provider custom-openai --api-key YOUR_KEY --base-url https://api.example.com/v1
lokit translate --provider custom-openai --model my-model
Dry run
lokit translate --provider copilot --model gpt-4o --dry-run
User Data Storage
All user data is stored in ~/.local/share/lokit/ (respects $XDG_DATA_HOME):
auth.json — OAuth tokens and API keys (permissions: 0600)
Credentials
Lookup order (highest → lowest):
--api-key flag
- Provider-specific environment variable (
GOOGLE_API_KEY, GROQ_API_KEY, OPENAI_API_KEY, OPENCODE_API_KEY)
- Stored credentials in
auth.json
System Prompts
Each target format has a built-in system prompt optimized for its structure (gettext, po4a/docs, i18next, vue-i18n, android, yaml, markdown, properties, flutter, js-kv, desktop, polkit). Prompts can be customized in two ways:
- Per target — set
prompt: in the target config in lokit.yaml
- Per run — use the
--prompt flag on the command line
The --prompt flag takes priority over the lokit.yaml target prompt, which takes priority over the built-in default. Use {{targetLang}} as a placeholder for the target language name.
Incremental Translation (lokit.lock)
lokit tracks MD5 checksums of source strings in a lokit.lock file (stored next to lokit.yaml). On subsequent runs, only new or changed strings are sent to the AI provider, saving tokens and time.
Key Filtering (locked_keys / ignored_keys / locked_patterns)
You can control which keys are translated per target in lokit.yaml:
targets:
- name: ui
format: i18next
dir: translations
pattern: "{lang}.json"
source_lang: en
languages: [ru, de, fr]
# Keys excluded from translation entirely (never sent to AI)
ignored_keys:
- debug_label
- internal_test_string
# Hand-curated translations preserved as-is (skipped even with --all)
locked_keys:
- app_name
- copyright_notice
# Regex patterns — matching keys treated as locked
locked_patterns:
- "^brand_.*"
- "^legal_"
Semantics:
| Field |
Effect |
Overridden by |
ignored_keys |
Key is completely skipped, as if it doesn't exist |
— |
locked_keys |
Existing translation is preserved, key is not re-translated |
--force |
locked_patterns |
Same as locked_keys but matches keys by regex |
--force |
ignored_keys are always skipped, even with --force.
locked_keys and locked_patterns are skipped during normal and --all runs. Only --force overrides them.
- These settings work with all formats: gettext PO, po4a, i18next, vue-i18n, Android, YAML, Markdown, .properties, Flutter ARB, js-kv, desktop, and polkit.
Development
Built with Go 1.23+:
- cobra — CLI framework
- yaml.v3 — YAML config parsing
- Native OAuth for GitHub Copilot and Gemini
License
MIT License — see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.