In Appium, when does an appium:language or appium:locale change take effect on Android and iOS?
answer
- capabilities are read once
- no in-session locale command on Android
- Apple simulators get an extra command
- configureLocalization is simulator-only
basics
~20 sBoth are session-start capabilities, so on Android and on Apple real devices a language or locale change needs a new session. Apple simulators are the exception: XCUITest's mobile: configureLocalization changes localization inside a live session.
solid answer
~40 s`language` and `locale` are Appium base capabilities, still written with the `appium:` prefix because only the W3C standard names may go bare. Being capabilities, they are read while the session is being created, so on Android the value you pass is the value you get for the whole session; changing it means tearing the session down and starting another. The Android drivers add `appium:localeScript` for a writing system that a language-and-country pair cannot pin, and it is a session-start capability too. Apple is where this leaf diverges: the XCUITest driver ships `mobile: configureLocalization`, a **simulator-only** execute method that changes localization inside a running session. On an Apple real device there is no such command, so you are back to capabilities and a fresh session, exactly like Android.
code
java · 14 linesimport org.openqa.selenium.MutableCapabilities;
final class LocaleSession {
static MutableCapabilities androidFrenchCanadian(String appPath) {
MutableCapabilities caps = new MutableCapabilities();
caps.setCapability("platformName", "Android");
caps.setCapability("appium:automationName", "UiAutomator2");
caps.setCapability("appium:app", appPath);
caps.setCapability("appium:language", "fr");
caps.setCapability("appium:locale", "CA");
return caps;
}
}go deeper
Be ready to say that appium:language and appium:locale are read when the session is created, so a different locale means a different session. Name the Apple simulator exception if you know it.
Explain why a capability cannot change mid-session, and that XCUITest's mobile: configureLocalization is the one in-session lever and works only on simulators. Mention appium:localeScript as the Android-only third knob.
Show that you would not build a locale switch into a page object at all, and be able to say exactly what a suite loses the day it moves from Apple simulators onto real hardware.
Own where the locale knob lives in the framework's configuration — something a session is built from rather than a runtime step — and defend that even on a fleet where simulators would let you cheat.
## A capability is read once, at session creation Appium's `language` and `locale` are base capabilities — they sit in the core's constraint list alongside `platformName`, `app`, `newCommandTimeout` and `udid`. Like every non-standard name they are sent with the `appium:` prefix. What matters here is not the spelling but the lifecycle: a capability is part of the `POST /session` body, so the driver reads it exactly once, while it is building the session. Nothing in the WebDriver protocol lets a test edit a capability afterwards. That single fact answers most of this question — for anything driven purely by `appium:language` and `appium:locale`, the setting takes effect when the session starts and never again. ## The Android answer On Android the language and locale knobs are capabilities and only capabilities. The Android drivers expose a very large execute-method surface — app lifecycle, connectivity, geolocation, permissions, clipboard, shell and much more — but no in-session locale twin. So an Android run gets the locale it was born with: - pass `appium:language` and `appium:locale` in the session's capabilities; - add `appium:localeScript` when a language and country pair is not enough to pin the writing system; - to exercise a second locale, end the session and start another with different values; - expect the change to be device-level rather than app-level, so it is not what `appium:noReset` or `appium:fullReset` govern. ## The Apple answer, and why this leaf exists The XCUITest driver accepts the same session-start capabilities, and on a real device that is all you get. On a **simulator** it also ships `mobile: configureLocalization`, an execute method that applies a localization configuration to the running target. That command is simulator-only: it leans on facilities the driver has against a simulator and not against physical hardware, so pointing it at a real device fails rather than quietly doing nothing. The consequence is a three-way split that is easy to state and easy to get wrong: 1. **Android, any target** — capability only, effective at session start. 2. **Apple real device** — capability only, effective at session start. 3. **Apple simulator** — capability at session start, plus `mobile: configureLocalization` inside the session. ## Compared with location, the shape is inverted It is worth holding this next to the other half of the same subject, because the two behave in opposite ways. Position is an in-session command on both platforms — `mobile: setGeolocation` on Android, `mobile: setSimulatedLocation` on Apple platforms — and no capability sets it. Locale is the mirror image: a capability everywhere, with one simulator-only command as the single exception. | Knob | Android | Apple simulator | Apple real device | |---|---|---|---| | Language and locale | `appium:language`, `appium:locale`, `appium:localeScript` at session start | those capabilities, plus `mobile: configureLocalization` in session | those capabilities only | | Position | `mobile: setGeolocation` in session | `mobile: setSimulatedLocation` in session | `mobile: setSimulatedLocation` in session | ## What it means in practice For the swimming-lesson booking app, imagine the timetable screen renders lesson times and prices from the device locale. Reaching a second locale is not a step you bolt onto an existing case on Android — it is a different session. The practical consequences: - the locale is a property of the session, so it belongs in the capability builder, not in a page object; - a helper that tries to switch locale mid-case works on an Apple simulator and throws on everything else, which is the worst failure mode there is because it passes on the developer's machine; - if a suite leans on `mobile: configureLocalization`, say so in the run's requirements: that suite cannot move to real Apple hardware unchanged; - reading a locale back is not symmetrical with reading a location back — there is no locale twin of `mobile: getGeolocation`, so assert through the app's own rendered text. ## Mistakes worth naming The first is assuming `appium:locale` alone pins a writing system; `appium:localeScript` exists on the Android side precisely because it does not. The second is sending `language` and `locale` bare because they are core capabilities — being a core capability is not the same as being one of the W3C standard names, and only those may go unprefixed. The third is generalising the simulator-only command into a cross-platform feature: `mobile: configureLocalization` belongs to the XCUITest driver, it is simulator-only, and it has no Android counterpart at all. The honest one-line summary is that Appium treats language and locale as something a session is *born with*, and gives exactly one target — the Apple simulator — the ability to change its mind afterwards.
- Why can't you change appium:locale in the middle of a running Appium session on Android?Capabilities are part of the `POST /session` body and the driver reads them once, while building the session; WebDriver has no command that edits a capability afterwards. The Android drivers also ship no in-session locale execute method, so the only lever left is a new session created with different `appium:language` and `appium:locale` values.
- What breaks if a suite leans on mobile: configureLocalization and then moves to Apple real devices?The command is simulator-only, so every case that switches locale mid-session starts failing on hardware. The fix is to promote the locale to a session-start capability — `appium:language` and `appium:locale` — and create a separate session per locale, which is the shape Android already forces on you.
- When does appium:localeScript earn its place on an Android session?When a language and country pair does not pin the writing system the app should render — the same language can be written in more than one script, and `appium:locale` has no room for that distinction. It is an Android-drivers capability read at session start, and the XCUITest driver has no counterpart to it.
saying these in an interview costs you the question
- Thinking appium:locale can be changed mid-session on Android
- Calling mobile: configureLocalization against an Apple real device
- Assuming appium:localeScript exists on the XCUITest driver
- Believing appium:fullReset resets the device language
- Sending language and locale without the appium: prefix