In fastlane, how do you choose screenshot locales on iOS versus Android?
answer
- capture runs once per locale
- the two option names differ by one word
- Android must put the device back afterwards
- languages plus localize_simulator on one side
basics
~20 sOn iOS, capture_ios_screenshots takes a languages list and can localize the simulator itself; on Android, capture_android_screenshots takes a locales list plus ending_locale, the locale the shared device is restored to once the capture run finishes.
solid answer
~40 sThe two actions spell it differently and behave differently. `capture_ios_screenshots` takes `languages`, and re-runs the whole XCUITest pass per language against each simulator in `devices`; `localize_simulator` switches the simulator's own language and region too, so system dialogs in a sailmaker measurement app's screenshots are not stuck in English while the app is French. `capture_android_screenshots` takes `locales`, drives the instrumentation suite once per locale, and additionally carries `ending_locale` — the locale the device is left in when capture ends — because it is mutating a real device or emulator that outlives the run. Both write one subdirectory per locale under `output_directory`, which is the shape the platform's upload action later reads.
go deeper
Recall that both capture actions take a list and run once per entry, and that the iOS option is called languages while the Android one is called locales. Getting the two names the right way round is most of the credit here.
Explain the mechanics: an XCUITest pass per language per simulator versus an instrumentation run per locale on a device, plus what localize_simulator adds on top of the app's own localization.
Demonstrate the operational half — ending_locale on shared Android hardware, seeded fixture data per locale, and how you notice a locale whose layout truncates before that artwork reaches a listing.
Own the scaling question: how many locales and device sizes are worth capturing, what that costs in capture minutes per release, and where hand-made artwork earns its keep instead.
## Locale is the reason this is automated at all A store listing is per-locale, and each locale carries its own screenshot set. For a sailmaker measurement app sold into English, French and Japanese lofts, that is three artwork sets per device size, and every one of them goes stale the moment the measurement sheet gains a field. Doing it by hand is the manual work automation exists to remove, so both fastlane capture actions treat 'the set of locales' as a first-class input — but they name it differently and clean up after themselves differently. ## iOS: languages, and a simulator that speaks them `capture_ios_screenshots` takes **`languages`**, a list of language or language-region identifiers. For each entry it replays the XCUITest pass on every simulator named in `devices`, launching the app in that localization, and writes the resulting PNGs into a per-language subdirectory of `output_directory`. Two neighbouring options carry most of the quality: - **`localize_simulator`** switches the *simulator's own* language and region as well. Without it you get a French app inside an English system: permission alerts, share sheets, the keyboard and date or number formatting all stay in the simulator's language, and those are exactly the pixels a reviewer notices. - **`launch_arguments`** passes per-run arguments into the app, which is how you seed locale-appropriate fixture data. A French screenshot of a sail measurement sheet full of English sample customers is worse than no screenshot at all. `dark_mode` and `override_status_bar` also change what the output looks like, but they are appearance, not locale, and it is worth being precise about that in an answer. ## Android: locales, and putting the device back `capture_android_screenshots` takes **`locales`** — the same idea, a different word — and runs the instrumentation test APK once per locale on a connected device or emulator. Because it changes the **system locale of a machine that outlives the run**, it carries an option the iOS action has no need for: **`ending_locale`**, the locale the device is restored to when capture finishes. That option is small, easy to omit from an answer, and exactly the detail that shows you have run this on shared hardware. On iOS the machine is disposable — the action can erase a simulator and nobody downstream cares. On Android the emulator or the phone on the shelf is the next job's machine too, so ending a run in the last locale of your list quietly breaks whatever comes next. Set `ending_locale` deliberately rather than inheriting whatever the run finished on. ## The divergence in one table | | iOS | Android | |---|---|---| | option name | `languages` | `locales` | | what runs per entry | an XCUITest pass per simulator in `devices` | an instrumentation run on the connected device | | system UI localization | `localize_simulator` | the device's own system locale is changed | | cleanup afterwards | the simulator is disposable, `erase_simulator` | `ending_locale` restores the device | | canonical action | `capture_ios_screenshots` (`snapshot`) | `capture_android_screenshots` (`screengrab`) | ## What lands on disk - Both actions write **one subdirectory per locale** under `output_directory`; that per-locale shape is the contract the upload action reads. - `clear_previous_screenshots` removes the previous run's images first, so a locale you dropped from the list does not linger as stale artwork. - Adding a locale is therefore a one-line change plus a capture run, not a design task — which is the whole payoff of automating capture. ## Traps in a localized capture lane 1. **Assuming one list covers both platforms.** They are separate lanes with separate option names, and the identifier formats you pass are not guaranteed to be spelled identically either. 2. **Localizing the app but not the system.** Without `localize_simulator` on iOS, system-drawn UI betrays the mismatch immediately. 3. **Ignoring layout, not just text.** German and Japanese strings change wrapping and truncation; seeing that is the point of capturing per locale, so a shot with clipped text is a finding, not a tooling defect. 4. **Forgetting the device is shared.** Skipping `ending_locale` on Android hands the next job a device speaking your last locale. 5. **Expecting the store to translate.** Neither store generates localized artwork from one source set; every locale's images are uploaded. ## What interviewers listen for A good answer names both options in the same sentence, explains why only one platform needs a restore step, and connects the per-locale output directories to what the upload action later consumes. A weak answer treats locale as a string you pass and stops there.
- What does localize_simulator change that passing languages alone does not?`languages` decides which app localization each capture pass launches in. `localize_simulator` additionally switches the simulator's own language and region, so system-drawn UI — permission alerts, share sheets, keyboard, date and number formatting — matches. Without it a French screenshot of the sailmaker measurement app can show a French app framed by English system dialogs.
- Why does capture_android_screenshots have ending_locale when the iOS action has nothing like it?Because it mutates a real device or emulator that outlives the run, while the iOS action drives simulators it can erase. `ending_locale` names the locale to leave the machine in once capture finishes, so the next job on that shared device does not silently inherit the last entry from your `locales` list.
saying these in an interview costs you the question
- Thinks one locale list serves both capture actions
- Expects the store to translate screenshots automatically
- Leaves a shared Android device in the last captured locale
- Assumes app language alone localizes system dialogs
- Believes locale affects text only, never layout or truncation