Documentation

Ship in every language.
Zero manual work.

Lokali watches your source locale file and opens a translation PR every time you push new strings. This page covers install, config, and the PR workflow.

01

Quickstart

Three steps from zero to automated translations. No CLI, no config files to write manually — Lokali's welcome PR creates everything for you.

1
Install the GitHub App

Visit github.com/apps/lokali and click Install. Select the repos you want Lokali to watch. Takes 30 seconds.

2
Lokali opens a welcome PR

Within a minute, Lokali scans your repo for a source locale file (e.g. messages/en.json, locales/en.json). If found, it opens a PR adding .lokali.yml and LOKALI.md with sensible defaults.

Welcome PR · your-org/your-repo
Open Welcome to Lokali — set your target locales
This PR adds .lokali.yml (config) and LOKALI.md (team quickstart) to your repo. Edit target_locales to pick your languages, then merge.
See a real welcome PR in lokali/demo-app →
3
Merge it and you're done

Merge the welcome PR. From now on, every push that touches your source locale file triggers a translation PR for all your target languages — automatically, within minutes.

💡
Want to customize which languages you ship to? Edit target_locales in .lokali.yml before merging. The full config reference is below.
🔍
Don't have a source locale file yet? Lokali will open a setup issue with instructions instead of a PR. Follow the issue, push your first en.json file, and Lokali picks it up automatically.
02

.lokali.yml

Drop a .lokali.yml in the root of your repo (Lokali's welcome PR does this automatically). Here's the full schema.

yaml
# .lokali.yml — full schema # Language code of your source strings (required) source: en # Target languages Lokali will translate into (required) targets: - es # Spanish - fr # French - de # German - ja # Japanese - pt # Portuguese # Glob pattern(s) for your locale files (required) # Use {lng} as placeholder for the language code paths: - messages/{lng}.json # Files/directories to exclude from translation (optional) exclude: - messages/keys.json - messages/_dev.json # Glossary — terms Lokali must never translate (optional) glossary: - Lokali - GitHub - Pro # PR strategy: one PR per push (default) or one PR per language (optional) pr_strategy: batch # "batch" | "per_language"
Key Type Description
source string BCP-47 language code for your source strings. Usually en. required
targets string[] List of target language codes. Add or remove codes to control which languages get PRs. required
paths string[] Glob patterns for locale files. Use {lng} as a placeholder for the language code. Lokali watches these paths for changes. required
exclude string[] Paths to skip. Useful for internal-only keys, generated files, or non-translatable locale data. optional
glossary string[] Terms that must never be translated. Brand names, product names, technical identifiers. Passed as hard constraints to the model. optional
pr_strategy string batch (default) — one PR per push, all languages in one branch. per_language — a separate PR per target locale. optional

Supported languages: Spanish, French, German, Portuguese (BR + PT), Japanese, Korean, Chinese Simplified, Chinese Traditional, Arabic, Hindi.

🇪🇸 es 🇫🇷 fr 🇩🇪 de 🇯🇵 ja 🇰🇷 ko 🇧🇷 pt 🇨🇳 zh 🇹🇼 zh-TW 🇸🇦 ar 🇮🇳 hi

Copy-paste configs per framework

yaml · .lokali.yml (next-intl)
# next-intl — messages/*.json structure source: en targets: [es, fr, de, ja, pt] paths: - messages/{lng}.json glossary: [Lokali]
📂
Lokali watches messages/en.json for changes. When you push new keys, it writes messages/es.json, messages/fr.json, etc. and opens a PR.
yaml · .lokali.yml (react-i18next)
# react-i18next — public/locales/{lng}/translation.json source: en targets: [es, fr, de, ja, pt] paths: - public/locales/{lng}/translation.json glossary: [Lokali]
📂
Source: public/locales/en/translation.json. Targets: public/locales/es/translation.json, etc. Works with multiple namespaces — add more entries to paths.
yaml · .lokali.yml (i18next)
# i18next — locales/{lng}.json structure source: en targets: [es, fr, de, ja, pt] paths: - locales/{lng}.json glossary: [Lokali]
📂
Source: locales/en.json. Targets: locales/es.json, locales/fr.json, etc. If you use namespaced files, add patterns like locales/{lng}/common.json.
yaml · .lokali.yml (vue-i18n)
# vue-i18n — src/locales/{lng}.json structure source: en targets: [es, fr, de, ja, pt] paths: - src/locales/{lng}.json glossary: [Lokali]
📂
Source: src/locales/en.json. Targets: src/locales/es.json, etc. Works with both JSON and YAML locale files — use .yml extension in the path if your project uses YAML.
yaml · .lokali.yml (Rails i18n)
# Rails i18n — config/locales/{lng}.yml structure source: en targets: [es, fr, de, ja, pt] paths: - config/locales/{lng}.yml exclude: - config/locales/devise.en.yml - config/locales/activerecord.en.yml glossary: [Rails, Devise]
📂
Source: config/locales/en.yml. Use the exclude list to skip gem-generated locale files like devise or activerecord that shouldn't be translated.
03

Translation PRs

Every push that touches your source locale file triggers Lokali. Within minutes, a translation PR appears with every target language updated.

PR title format

text
🌍 Translate 4 new strings → es, fr, de, ja

PR body format (example)

Open 🌍 Translate 4 new strings → es, fr, de, ja
## New strings - `nav.settings` - `onboarding.welcome_message` - `errors.not_found` - `dashboard.empty_state` ## Files updated - messages/es.json (Spanish: 4 strings) - messages/fr.json (French: 4 strings) - messages/de.json (German: 4 strings) - messages/ja.json (Japanese: 4 strings)
See a live example PR in lokali/demo-app →

How to review

1
Skim by locale

Each locale file is a separate diff. Review the language you know first — check tone and proper nouns. The rest is usually correct without review.

2
Check your glossary terms

If you've set a glossary in .lokali.yml, Lokali hard-codes those terms as untranslated. Verify they're preserved correctly.

3
Approve or request changes per file

Use GitHub's standard PR review. If a specific locale needs adjustment, leave a comment or edit the file directly in the PR branch.

✏️
Overriding a translation? Just edit the target file in the PR branch before merging. Lokali respects existing values by default — it only writes keys that are missing or changed in the source.
04

FAQ

Edit the targets list in your .lokali.yml and push. Lokali detects the config change and opens a PR with the new language translated from your source file. No other setup needed.

Yes. Add terms to the glossary key in .lokali.yml. Anything in the glossary is passed as a hard constraint to the model — it will never be translated, transliterated, or paraphrased. Useful for product names, technical terms, and trademarks.

Edit the target locale file directly — either in the PR branch before merging, or in your main branch after. Lokali respects existing values by default: it only writes keys that are new or changed in the source. Your manual overrides stay intact.

Within minutes of the push that touches your source locale file. Most PRs appear in under 3 minutes. During high-load periods it may take up to 10 minutes. There is no manual queue — processing starts automatically when the webhook fires.

GPT-4o-mini with the full diff context plus your glossary and repo language as constraints. The model sees the entire key-value structure of your source file, not just isolated strings — this gives it enough context to translate idioms and UI-specific language correctly.

No source code is sent to OpenAI. Lokali only sends the changed key-value pairs from your locale file — the actual translation strings — plus minimal context (your repo's primary language detected from the README, and your glossary). No routes, no components, no business logic, no secrets. The privacy boundary is: if it's not in your locale JSON/YAML, it doesn't leave your repo.

Go to GitHub Settings → Applications → Lokali → Configure → Uninstall. Lokali immediately stops watching your repos. Your existing locale files stay exactly as they are — nothing is deleted. You can also remove .lokali.yml and LOKALI.md manually afterward if you want a clean slate.

Yes. Add multiple entries to paths to cover nested packages. For example:

paths: [apps/web/messages/{lng}.json, packages/ui/locales/{lng}.json]

Lokali watches each glob independently and groups changes from the same push into a single PR.

Ready to ship every language?

Install takes 30 seconds. First translation PR on your next push.