CI/CD
Xcode build phase
Pull the latest text on every build, from a script phase that runs before Compile Sources.
What you get
The latest text in every build, without anyone remembering.
Scriptable from the CLI
Push, pull and sync from a terminal, a build phase or a coding agent's shell, with a token in the environment.
The CLIRuns in CI
Push the source language on merge and pull every language before the release build, on any CI that can run a shell.
CI pipelinesUpdates over the air
Publish the verified strings and let the running app fetch them, so a fixed translation reaches users without a store release.
Over-the-air deliveryAI drafts, a person verifies
Every language is drafted against your glossary and each key's length limit. A draft never ships until someone has verified it.
Set it up
From nothing to every language.
Step 1: Vendor the CLI
Commit the script so the version is pinned with the project. Keep anylocale in the file name; that name is what selects the product.
shellcurl -fsSL https://anylocale.com/anylocale.sh -o Scripts/anylocale chmod +x Scripts/anylocaleStep 2: Add a Run Script phase
Above Compile Sources, with the token read from the environment rather than a stored login, which the build user may not have. List the written files under Output Files so Xcode does not rerun the phase on every incremental build.
One pull replaces the catalog in place.
Run Script# Pull the latest text before compiling export ANYLOCALE_TOKEN="${ANYLOCALE_TOKEN:?set in the scheme or CI}" "$SRCROOT/Scripts/anylocale" pull --project my-app --locale en \ --format xcstrings --platform ios --out "$SRCROOT/Localizable.xcstrings"Sync writes every locale's folder, .stringsdict included.
Run Script# Pull the latest text before compiling export ANYLOCALE_TOKEN="${ANYLOCALE_TOKEN:?set in the scheme or CI}" "$SRCROOT/Scripts/anylocale" sync --project my-app --platform ios \ --out-dir "$SRCROOT/Sources/Resources"Step 3: Give the scheme the token
Locally through the scheme's environment variables, in CI through a secret. The token needs the read scope only.
Good to know
- Files land in place only when they arrived complete, so an interrupted build never leaves a half-written .strings file.
- The phase exits non-zero when a locale failed to download, which fails the build rather than shipping stale text unnoticed.
Questions
- Can an interrupted build leave a half-written file?
- No. Each file lands in place only when it arrived complete, so a build cancelled mid-download keeps the previous .strings file.
- Which scope does the token need?
- read only. Keep the token in the scheme's environment locally and in a secret in CI; the phase never needs push or manage.
- Why vendor the script instead of installing the CLI?
- So the version is pinned with the project and every machine that builds it runs the same one, including a CI runner with no Homebrew.
- Do I get unverified text when I pull?
- Yes. A pull carries the current text of every key, verified or not, so a build always has something to show. Only over-the-air delivery is limited to verified strings.
Start with the file your app already ships.
After checkout, import one strings file and read the first drafts within minutes.
Nothing to connect and nothing to install. The CLI is optional.