Platforms
iOS
Keep localizing through the files Xcode already builds. anylocale reads the string catalog or the .lproj tree and hands back every language.
What you get
Everything the editor does, through the files you already ship.
AI 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.
Every plural form a language has
Each locale gets exactly the CLDR categories it uses, Arabic six and Japanese one, written in the format's own plural shape.
Updates 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 deliveryPulls on every build
A Run Script phase above Compile Sources keeps the target on the latest verified text without anyone remembering to sync.
Xcode build phaseOne catalog, every platform
The iOS app, the Android app and the web app share one project. Tag the keys only one of them uses and pull that subset alone.
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 CLI
Set it up
From nothing to every language.
Step 1: Keep writing SwiftUI as you do
Every
Text("key")with a comment lands in the string catalog on the next build. That catalog is what anylocale reads, so the source language stays in the code where it is written.ContentView.swiftText("welcome_title", comment: "Headline on the first screen")Step 2: Install the CLI and log in
Homebrew or the one-line installer, then a token issued per project under Settings, Integrations. The read scope pulls; push writes source files and values; manage creates and deletes keys.
shellbrew install anylocale/tap/anylocale anylocale login --project my-appStep 3: Push the source language
From a string catalog or from the base .lproj. Descriptions in the file become the notes translators and the AI draft see.
shellcurl -fsS -X POST "https://anylocale.com/api/loc/push?project=my-app&format=xcstrings" \ -H "Authorization: Bearer $ANYLOCALE_TOKEN" \ --data-binary @Localizable.xcstringsStep 4: Pull every language into the target
Which command depends on what the target reads. Add --platform ios to leave out keys tagged for Android.
One file carries every locale, so one pull replaces the catalog in place.
shellanylocale pull --project my-app --locale en --format xcstrings \ --platform ios --out Localizable.xcstringsWrites the
<locale>.lprojfolders the target already references, with a .stringsdict beside each .strings that has plurals.shellanylocale sync --project my-app --platform ios \ --out-dir Sources/ResourcesStep 5: Make it a build phase
So every build carries the latest text. The Xcode build phase guide has the script for both layouts.
Step 6: Add the Swift package
Swift Package Manager, iOS 16 and macOS 13 upward, Xcode 16. In Xcode: File, Add Package Dependencies, enter the URL and add the
Anylocalelibrary to your target. Or declare it in Package.swift.Package.swiftdependencies: [ .package(url: "https://github.com/anylocale/anylocale-swift", from: "1.1.0") ], targets: [ .target(name: "MyApp", dependencies: [ .product(name: "Anylocale", package: "anylocale-swift") ]) ]Step 7: Initialise once, fetch on launch
Under Delivery, publish a distribution and create a key for the iOS SDK; its URL is the only configuration.
initializeloads the cached strings synchronously,remoteFetchdownloads the current language and answers a 304 when nothing changed.MyApp.swiftimport SwiftUI import Anylocale @main struct MyApp: App { init() { Anylocale.shared.initialize( cdn: URL(string: "https://anylocale.com/ota/v1/<distribution-key>")!) } var body: some Scene { WindowGroup { ContentView() .task { await Anylocale.shared.remoteFetch() } } } }Step 8: Read strings
Two ways to get the downloaded text on screen. Both fall back to the strings compiled into the app for any key the distribution does not carry.
Explicit calls, no runtime patching.
AnylocaleTextre-renders when a download lands,translatetakes format arguments and a table name.ContentView.swiftimport SwiftUI import Anylocale struct ContentView: View { var body: some View { VStack { AnylocaleText("welcome_title") Text(Anylocale.shared.translate("items_count", 5)) Text(Anylocale.shared.translate("hello", table: "common")) } } }Existing code stays as it is. Pass
enableSwizzling: truetoinitializeandNSLocalizedString,String(localized:), storyboards, XIBs and SwiftUI'sText("key")resolve through the SDK. A download shows in a swizzledTexton the next launch. Plurals go through the compiled .stringsdict or the explicittranslate, never through the swizzle.MyApp.swiftAnylocale.shared.initialize( cdn: URL(string: "https://anylocale.com/ota/v1/<distribution-key>")!, enableSwizzling: true )ContentView.swiftimport SwiftUI struct ContentView: View { var body: some View { VStack { Text("welcome_title") Label("settings_title", systemImage: "gear") Text(NSLocalizedString("error_no_connection", comment: "")) } } }
Good to know
- Placeholders such as %@ and %lld are stored in a platform-neutral form and rendered back in Apple syntax.
- Languages must exist in the Xcode project; a sync does not add a localization the target does not declare.
- A SwiftUI Text resolves its string when it first renders, so a download shows on the next launch; AnylocaleText updates in place.
Questions
- Do I need the SDK?
- No. Without it, the text ships with each build through sync, and nothing changes in how the app reads strings. The SDK adds one thing: fetching the verified strings between releases, so a fix reaches users without a store update.Over-the-air delivery
- Does the SDK work with SwiftUI?
- Yes. AnylocaleText re-renders the moment a download lands. With swizzling on, a plain Text("key"), Label and NSLocalizedString resolve through the SDK, and a download shows on the next launch.
- String catalog or .lproj folders?
- Either. A string catalog is pushed and pulled whole; a legacy target syncs its .lproj tree with one .strings and, where there are plurals, one .stringsdict per table. Pull whichever your target reads.
- Which iOS versions does the SDK support?
- iOS 16 and macOS 13 upward, built with Xcode 16, as a Swift package. Older deployment targets keep using sync without the SDK.
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.