Guide
Why your fastlane snapshot screenshots are all in English (and how to check every language)
You set languages(["en-US", "de-DE", "ja"]) in your Snapfile, ran fastlane snapshot, and opened the folders. German and Japanese are there, and every image is in English.
I build a tool in this area (shotfleet, which comes up at the end), so read this with that in mind. The first four causes below need nothing from me.
How snapshot is supposed to set the language
fastlane's docs say the language reaches your UI tests "via a temporary file which is written by snapshot before running the tests". Your test target includes SnapshotHelper.swift, and the docs tell you to call setupSnapshot(app) before app.launch(). That helper reads the file and passes the language to your app as launch arguments. There is also an option, localize_simulator, that sets the Simulator's own system language.
So there are several places where the chain can break. The GitHub issues are old but show the pattern. In #8895 the Simulator language "stays en-US" after an Xcode update. In #12917 the reporter got English from fastlane snapshot while a manual Xcode run with the generated language file switched correctly. In #11457 the reporter found that localize_simulator true worked but changed the status bar because the simulator was erased. I did not reproduce any of these; they are the documented symptom, from 2017 and 2018. All three are closed.
Five things to rule out, in order
1. setupSnapshot(app) runs after app.launch(), or never. The docs say to call it before launch, in setUp(). If your test launches the app first, the language never reaches it.
2. You ran the test from Xcode. The docs say running tests in Xcode does not produce snapshots; only the fastlane snapshot command creates the language file and the folders.
3. The Simulator system language. Try localize_simulator(true) in your Snapfile. Per issue #11457 the cost is a status bar that looks different, because the simulator gets erased.
4. The app is not translated into that language. If de is in your Snapfile but your build has no German strings, iOS shows your base language and no setting will help. List what your build really ships:
ls path/to/MyApp.app | grep lproj
Compare that list with your Snapfile. The app's base language may not be listed: with a String Catalog that has no explicit English entries, my test build had de.lproj and ja.lproj and no en.lproj. A language that is in the Snapfile but not in the app can only ever produce your base language. I checked this on a small test app: with de.lproj deleted from the build, launching with German arguments showed English, and Japanese on the same build still showed Japanese.
5. The app remembers something. If your app stores its own language choice or onboarding state, a reused install can show the old language. snapshot has reinstall_app and erase_simulator for this. On a small test app that saves its own language, launching with German arguments still gave English, and uninstalling and installing the app again gave German (I did that by hand, not with snapshot's option). This and the previous cause are not documented cases from the issue threads, so test them on your app.
Then: look at every image
With 18 languages and 4 screens that is 72 images. Opening them by hand works until the day you skip one. A faster way is to compare each screenshot with the text your app really contains.
Then: check the folder you already have
shotfleet's check command does that, and it is free: no licence, no account. It does not capture anything and does not touch your fastlane folders. It runs on a Mac and reads each image with the text recognition built into macOS. Give it a simulator build of your app, so it knows your real strings:
xcodebuild -scheme MyApp -sdk iphonesimulator -configuration Debug \
-derivedDataPath build build
shotfleet check fastlane/ \
--app build/Build/Products/Debug-iphonesimulator/MyApp.app
For an Android folder, pass the APK instead: --app path/to/app-release.apk.
It reads each image and tells you:
- Wrong language: the
de-DEfolder shows English strings. - Copies: the same image in two languages.
- Missing: a language that did not produce every screenshot.
- Store rules: sizes, counts and transparency that App Store Connect or Play would reject.
- A listing in a language the app does not have: for example Traditional Chinese screenshots when the app has no Traditional Chinese.
The report (check.json and an index.html grid with a row per language and a column per screen, problems outlined in red) goes to ./shotfleet-check.
On the committed fastlane screenshots of my own workout app (252 iOS images) it found one real problem: Traditional Chinese listings with Chinese captions over an app that was still in English. When I planted mistakes in a copy of a clean set (a German screen in English, a Korean screen in Japanese, two copied images), each one was reported. On 220 screenshots of another of my apps (20 languages) a check took 57 to 86 seconds once macOS text recognition was warm. The first check after a restart or a macOS update is slower, because macOS compiles its text-recognition model; that can take minutes, and once took about 40 minutes.
Pass --app. Without it check falls back to language detection, which cannot judge short screens.
What this does not tell you
- If
checksays "macOS text recognition didn't answer in time" (or "isn't answering"), macOS is usually still compiling its text-reading model, which can take minutes on a busy Mac the first time (once about 40 minutes on a quiet one).checkdoesn't fail over it: it finishes and marks the screens it couldn't read as "not verified". Run it again later, or install Tesseract (brew install tesseract tesseract-lang) andcheckuses it automatically. No restart needed. - It says the language is wrong. It does not say why. Go back to the five causes.
- macOS text recognition reads 33 languages on macOS 27 (older versions read fewer). For other scripts (Greek, Hebrew, most Indic scripts)
checkstill catches other-language screens, copies and missing screens, and says which screens it could not read. With Tesseract installed,checkuses it for those scripts by itself: in my test, 84 of 85 languages could then be read, against 66 without it. - Copies are only reported on screens with enough text. Two near-empty screens that are identical can pass.
- It is only as good as your simulator build matching the build that made the screenshots.
When not to use shotfleet
If your screenshots are already right in every language, you do not need it. If you have only two or three languages, looking at the images yourself is fine. If you already have a maintained UI-test suite and snapshot works for you, keep snapshot; it is free and check can sit next to it. If you would rather capture with Maestro, one Maestro flow in every language shows how, without shotfleet. The tool only runs on an Apple silicon Mac (the installer refuses Intel), and capturing with shotfleet run is a separate step with its own requirements (Xcode, the Android SDK for Android, Maestro 2.x, Java 17+, and a Maestro flow you write). It does not make frames or captions and does not upload to the stores. I also have no data yet on how often modern fastlane versions hit the problem in this article; the issue threads are old.
Where to go from here
If check finds wrong-language images and you would rather not maintain per-language UI tests at all, shotfleet also captures: one English Maestro flow, every language your app ships, on iOS and Android. run is free for up to 2 languages. A licence unlocks every language and export: $29 for the first 100 buyers, then $49 once, with a year of updates and a 14-day refund. Details at shotfleet.com/#price.
The free part is the check command above. Install it, point it at your fastlane/ folder and read the grid.