langcodec is a localization CLI for teams shipping real apps, not demo files.
It handles the annoying parts of localization work in one place: format conversion, catalog cleanup, AI-assisted translation, translator-facing comment generation, and Tolgee sync for Apple string catalogs.
Supported formats:
- Apple
.strings - Apple
.xcstrings - Apple/Xcode
.xliff - Android
strings.xml - CSV
- TSV
Most localization tooling does one small thing. langcodec is designed to cover the loop teams actually run:
- Convert strings between iOS, Android, and spreadsheet formats.
- Inspect what is missing, stale, or still needs review.
- Normalize files so diffs stop being noisy.
- Draft translations with AI.
- Generate better comments for translators from real source usage.
- Pull from and push back to Tolgee without custom glue scripts.
langcodec translate \
--source Localizable.xcstrings \
--source-lang en \
--target-lang fr,de,ja \
--provider openai \
--model gpt-5.4translate is built for app catalogs, not just raw text:
- updates multi-language files like
.xcstringsin place - supports single-language Apple
.stringsand Androidstrings.xmlfiles too - supports multiple target languages in one run
- can prefill from Tolgee before using AI fallback
- shows live progress with
--ui auto|plain|tui - validates output before model requests
- prints a clear result summary at the end
langcodec annotate \
--input Localizable.xcstrings \
--source-root Sources \
--source-root Modules \
--provider openai \
--model gpt-5.4annotate looks through your codebase and writes better translator comments for .xcstrings, Apple .strings, and Android strings.xml files while preserving manual comments.
langcodec annotate \
--input en.lproj/Localizable.strings \
--source-root Sources \
--provider openai \
--model gpt-5.4langcodec tolgee pull
langcodec tolgee push --namespace WebGameTolgee support in v1 is intentionally focused on Apple .xcstrings. langcodec.toml can now be the source of truth, and langcodec will synthesize the Tolgee CLI JSON config at runtime.
brew tap oops-rs/tap
brew install langcodec-clicargo install langcodec-cliUse the CLI help for exact flags:
langcodec --help
langcodec translate --help
langcodec annotate --help
langcodec tolgee --helplangcodec convert -i Localizable.xcstrings -o translations.csv
langcodec convert -i translations.csv -o values/strings.xml
langcodec convert -i Localizable.xcstrings -o Localizable.xliff --output-lang fr
langcodec convert -i Localizable.xliff -o Localizable.xcstringsFor .xliff output, pass --output-lang to choose the target language. Use --source-language when the source language is ambiguous.
langcodec view -i Localizable.xcstrings --status new,needs_review --keys-only
langcodec stats -i Localizable.xcstrings --jsonlangcodec edit set -i en.strings -k welcome_title -v "Welcome"
langcodec edit set -i values/strings.xml -k welcome_title -v "Welcome"langcodec normalize -i 'locales/**/*.{strings,xml,csv,tsv,xcstrings}' --checknormalize, edit, and sync intentionally do not operate on .xliff in v1; convert XLIFF into a project format first.
langcodec sync --source source.xcstrings --target target.xcstrings --match-lang en
langcodec merge -i a.xcstrings -i b.xcstrings -o merged.xcstrings --strategy last[openai]
model = "gpt-5.4"
[translate]
concurrency = 4
use_tolgee = true
[translate.input]
source = "locales/Localizable.xcstrings"
lang = "en"
status = ["new", "stale"]
[translate.output]
lang = ["fr", "de"]
status = "translated"
[tolgee]
project_id = 36
api_url = "https://tolgee.example/api"
api_key = "tgpak_example"
namespaces = ["WebGame"]
[tolgee.push]
languages = ["en"]
force_mode = "KEEP"
[[tolgee.push.files]]
path = "locales/Localizable.xcstrings"
namespace = "WebGame"
[tolgee.pull]
path = "./tolgee-temp"
file_structure_template = "/{namespace}/Localizable.{extension}"
[annotate]
input = "locales/Localizable.xcstrings"
source_roots = ["Sources", "Modules"]
concurrency = 4Then run:
langcodec translate
langcodec annotate
langcodec tolgee pullWhen exactly one provider section is configured, translate and annotate use it automatically. If you configure multiple providers, choose one with --provider or translate.provider.
For larger repos:
- use
translate.input.sources = [...]to fan out translation runs - use
annotate.inputs = [...]to annotate multiple catalogs in place
convert: convert between localization formatsview: inspect entries, statuses, and keysstats: summarize coverage and completionedit: add, update, or remove entriesnormalize: rewrite files into a stable formdiff: compare two localization filessync: update existing target entries from a source filemerge: combine multiple inputs into one outputtranslate: draft translations with AI-backed providerstolgee: pull and push mapped.xcstringscatalogs with Tolgeeannotate: generate translator-facing.xcstringscomments with AI-backed source lookupdebug: inspect parsed output as JSON
langcodec shines when you are:
- shipping both iOS and Android apps
- moving strings through translators, spreadsheets, and app catalogs
- trying to reduce localization drift in CI
- replacing fragile one-off scripts with one repeatable tool
- Root overview: README.md
- Rust library crate: langcodec/README.md
MIT