|
Documentation
Book a DemoPlatform
PlatformMCPCLIAPIWorkflows
Guides
Changelog

Localization

  • Overview
  • Translation API
  • Web App Localization
  • Mobile App Localization
  • iOS with String Catalogs
  • Android with strings.xml
  • Emails Localization
  • Static Content (e.g. .md, .json)
  • Next.js with Markdoc
  • Rails with i18n

Workflows

  • Engine Setup with MCP
  • Jira Triage
  • CI/CD

Mobile App Localization

The Lingo.dev CLI translates native mobile resource files - Xcode .strings, Android XML, Flutter ARB, and React Native JSON - through a configured localization engine. The CLI auto-detects each file format from its extension, preserves structure, and handles plurals natively.

Platform Overview#

PlatformNative formatTypical source file path
iOS (Xcode).stringsen.lproj/Localizable.strings
iOS (Xcode).stringsdicten.lproj/Localizable.stringsdict
iOS (Xcode).xcstringsLocalizable.xcstrings
Androidstrings.xmlapp/src/main/res/values-en/strings.xml
Flutter.arblib/l10n/app_en.arb
React Native.jsonsrc/locales/en.json

Prerequisites#

Every CLI run sends content through a localization engine - the configuration that determines which LLM model, glossary, brand voice, and instructions apply. Create one in the Lingo.dev dashboard.

Install the CLI (Node.js 22+) and authenticate:

bash
npm install -g @lingo.dev/cli
lingo login

lingo login signs you in with a one-time code. For CI, skip the interactive login and pass --api-key (or set LINGO_API_KEY).

Configure Your Platform#

Run lingo init to create .lingo/config.json (source/target locales plus your file patterns), then lingo link to attach your orgId and engineId. Commit .lingo/config.json to your repo. The examples below show the resulting config for each platform - the source path always contains the source locale code, and the CLI substitutes it for each target locale (en.lproj -> de.lproj, values-en -> values-de, app_en.arb -> app_de.arb).

Xcode supports three localization formats. Use the one that matches your project setup.

String Catalogs (.xcstrings) - the modern Xcode format introduced in Xcode 15. A single JSON file contains all locales, and Xcode updates it automatically when you add new strings. The CLI mutates this file in place, so the pattern points at the single catalog with no locale segment.

json
{
  "orgId": "org_...",
  "engineId": "eng_...",
  "sourceLocale": "en",
  "targetLocales": ["es", "fr", "de", "ja"],
  "files": [{ "pattern": "MyApp/Localizable.xcstrings" }]
}

Legacy .strings files - one file per locale in [code].lproj/ directories. The source locale lives in the path (en.lproj) and the CLI writes each target into its own .lproj directory. If your project also uses .stringsdict for plurals, add a second files entry.

json
{
  "orgId": "org_...",
  "engineId": "eng_...",
  "sourceLocale": "en",
  "targetLocales": ["es", "fr", "de", "ja"],
  "files": [
    { "pattern": "MyApp/en.lproj/Localizable.strings" },
    { "pattern": "MyApp/en.lproj/Localizable.stringsdict" }
  ]
}

See Apple's localization documentation for setting up Xcode's i18n infrastructure.

Running Translations#

Translate all resource files in one command:

bash
lingo push

The CLI reads your source locale files, computes what changed since the last run using the lockfile (.lingo/lock.json, which you commit), translates only the delta, and writes results to target locale files.

On the first run - or whenever you add a new target locale - translate everything from scratch:

bash
lingo push --backfill-missing

Target a specific platform when your project contains multiple resource types by passing a glob (there are no --bucket or --target-locale flags):

bash
lingo push "app/src/main/res/values-en/strings.xml"
lingo push "MyApp/Localizable.xcstrings"

To fetch the latest translations elsewhere (for example on another machine), run lingo pull. To verify translations are up to date without writing changes - useful as a deploy gate - run lingo check.

Plurals and Platform Conventions#

Each mobile platform handles plural forms differently - iOS uses .stringsdict or String Catalog rules, Android uses <plurals> XML elements, and Flutter uses ICU MessageFormat in ARB files. The CLI preserves each platform's native plural structure during translation and generates the correct plural categories for each target locale.

Translator notes

Mobile strings are often short and context-dependent. Use translator notes in Xcode .xcstrings files to give the localization engine context about where a string appears - "button label in checkout flow" translates differently than "navigation menu item."

Automating in CI#

The recommended way to keep translations current is the Lingo.dev GitHub App. It runs server-side, reads your committed .lingo/config.json and engineId, and opens translation updates automatically - no runner, secret, or lockfile management on your side. If you prefer to run translations in your own pipeline, execute lingo push in your CI runner and commit the results.

Platform Deep Dives#

iOS with String Catalogs
End-to-end guide for Xcode .xcstrings with the CLI and GitHub App
Android with strings.xml
End-to-end guide for Android XML resources with the CLI and GitHub App

Next Steps#

Supported Formats
Full reference for all mobile file formats
Glossaries
Lock brand names and technical terms from translation
GitHub App
Automate mobile translations on every push
Key Locking
Copy specific values without translating them

Was this page helpful?

Max PrilutskiyMax Prilutskiy·Updated 5 days ago·4 min read