ScreenshotNeo

BlogHow-to

How to Perform Localization Testing with Selenium WebDriver

Use Selenium to repeat critical workflows across supported locales, then combine automated checks with visual and expert linguistic review.

By the ScreenshotNeo team4 October 202610 min read

Selenium WebDriver can repeat browser workflows under different language and locale conditions, helping you check that localized versions behave consistently. It cannot tell whether a translation is accurate or culturally appropriate. Treat localization testing as layered QA: automate functional checks, inspect the rendered experience, and involve a target-language reviewer. Selenium WebDriver controls a browser as a user would, locally or on a remote machine; Microsoft describes localization testing as checking translation quality alongside visual and functional issues (Microsoft Learn).

1. Plan locales and risks before writing tests

A language identifies a language, such as Arabic. A locale represents language and regional preferences, often expressed with a BCP 47 tag such as fr-CA or en-GB. The exact tags and behaviors to test must come from your product’s supported markets; a few examples do not represent every locale.

  1. List the supported language and regional variants, including fallback behavior.
  2. Choose critical journeys: sign-in, search, forms, checkout, and key error and success states.
  3. For each locale, note meaningful differences: direction, dates, numbers, currency, sorting, address or phone conventions, and market-specific workflow.
  4. Prioritize cases by the behavior they exercise and the impact on critical journeys. Include right-to-left (RTL), non-Latin scripts, and distinct regional formats when they are in scope.
  5. Record expected behavior separately from the translated text itself.

Internationalization work is normally a prerequisite: the application must be able to handle translated strings, Unicode, and locale-sensitive presentation before localized versions can be validated effectively. Microsoft separates functional, visual, linguistic, and market-specific validation in its localization testing guidance.

2. Choose how the application receives its locale

Set the application’s language or locale through the mechanism it actually supports. Common choices include a language selector, a locale-specific URL, an account preference, or a request setting. Browser locale emulation is a separate control: it can affect browser-exposed preferences, but it does not automatically switch an app whose locale is controlled by an account or URL.

Selenium’s Python API documentation for version 4.43.0 documents WebDriver BiDi methods for locale and time-zone overrides. The locale uses a BCP 47 tag, while the time zone takes an IANA name or offset string. Availability depends on the browser and Selenium binding; verify the combination you use before making the override part of required coverage. See the Selenium Python BiDi emulation API and Selenium WebDriver BiDi documentation.

3. Run the same journey for each locale

The example below uses Python and Chrome with Selenium 4.43.0. It explicitly sets the app locale through a query parameter, then requests browser locale and time-zone emulation through BiDi. The app URL and its locale mechanism are examples: adapt them to your application. If your app uses a selector or account preference, use that supported mechanism instead of the example query parameter.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

BASE_URL = "https://example.test/checkout"
CASES = [
    {"locale": "en-GB", "timezone": "Europe/London", "expected_total": "£1,234.56"},
    {"locale": "fr-CA", "timezone": "America/Toronto", "expected_total": "1 234,56 $"},
]

for case in CASES:
    options = webdriver.ChromeOptions()
    # BiDi support is required for the emulation calls below.
    options.enable_bidi = True
    driver = webdriver.Chrome(options=options)
    try:
        # This example app accepts its locale in the URL.
        driver.get(f"{BASE_URL}?locale={case['locale']}")

        # Browser emulation is independent of the app's locale-selection method.
        driver.bidi_connection
        emulation = driver.bidi_connection.session.execute
        emulation("emulation.setLocaleOverride", {"locale": case["locale"]})
        emulation("emulation.setTimezoneOverride", {"timezone": case["timezone"]})

        wait = WebDriverWait(driver, 15)
        total = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='order-total']")))
        assert total.text == case["expected_total"], (
            f"{case['locale']}: expected {case['expected_total']!r}, got {total.text!r}"
        )

        # Prefer stable, locale-neutral identifiers for functional assertions.
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='place-order']"))).click()
        wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='order-confirmation']")))
    finally:
        driver.quit()

BiDi API note: BiDi support and Python calling interfaces can vary across Selenium releases and browsers. The API page documents set_locale_override(locale, contexts, user_contexts) and set_timezone_override(timezone, contexts, user_contexts); use the binding’s documented interface for your installed version. If the example’s session call is not supported in your environment, keep the app-level locale setup and use the current binding API documented by Selenium. Do not silently treat an unsupported override as a passing locale test.

For a baseline that does not rely on browser emulation, use the app’s own locale switch and assert stable outcomes:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

locales = ["en-GB", "fr-CA"]
driver = webdriver.Chrome()
try:
    for locale in locales:
        driver.get("https://example.test/settings/language")
        selector = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='language-selector']"))
        )
        selector.click()
        driver.find_element(By.CSS_SELECTOR, f"[data-locale='{locale}']").click()
        WebDriverWait(driver, 10).until(
            EC.text_to_be_present_in_element_attribute(
                (By.TAG_NAME, "html"), "lang", locale
            )
        )
        driver.get("https://example.test/checkout")
        assert driver.find_element(By.CSS_SELECTOR, "[data-testid='place-order']").is_displayed()
finally:
    driver.quit()

The selectors and app endpoints in these snippets are placeholders. Use stable test IDs or other application-owned identifiers in your project. Do not make test success depend on an English button label that is expected to change by locale.

4. Separate behavior assertions from localized presentation

Check functional parity using stable identifiers, successful state transitions, and locale-neutral underlying values. Check formatted output separately. For example, verify that the order’s stored amount is 1234.56 in the application or test API, then verify that the UI formats it according to the selected locale and currency. Avoid parsing a displayed currency string as if it were an unambiguous machine value.

Dates such as 4/7 can mean different calendar dates in different conventions, and separators in number and currency strings vary. The W3C Internationalization Best Practices recommends locale-neutral machine-readable representations because they are less open to misinterpretation. Use the product’s specified locale rules as the expected display; do not assume one formatting convention is correct for every market.

5. Build a coverage matrix for locale-sensitive cases

Area What to check Useful assertion approach
Language selection and fallback Requested locale is applied; unsupported or missing translations follow the intended fallback. Assert the selected locale or document lang, then check representative content and fallback state.
Text fit and layout Longer translations do not overlap, clip, or hide actions; fonts render required scripts. Check element visibility and layout constraints, then visually inspect representative pages.
RTL and mixed direction Reading order, alignment, navigation, icons, and embedded Latin values behave correctly. Check direction metadata and key element positions; review mixed-direction content visually.
Dates and time zones Display and boundary behavior across the product’s supported time zones. Fix the test instant; assert localized display separately from stored timestamps.
Numbers, currency, and units Grouping, decimal separators, currency placement, digits, and unit presentation. Compare expected display for the exact locale and verify underlying values independently.
Sorting, search, and pluralization Locale-sensitive ordering, matching, and singular/plural messages. Use datasets containing relevant accented or non-Latin values and boundary quantities.
Input conventions and market flows Names, addresses, postal codes, phone numbers, payment or contact options relevant to the market. Use valid locale-specific fixtures and test acceptance, validation, and persistence.

For repeatable tests, freeze time or use a controlled test clock where your application supports it. Include values around meaningful boundaries: midnight near a date change, zero/one/many for plural forms, large values with separators, and names containing supported non-ASCII characters. Keep fixtures appropriate to the product’s supported markets rather than assuming every country uses the same conventions.

6. Add visual and linguistic review

Automation can catch missing controls, broken navigation, and some layout symptoms, but it cannot establish that copy is correct, natural, or culturally suitable. Review representative rendered pages at the target viewport and ask a target-language expert to validate in-context meaning. Microsoft’s guidance distinguishes visual and linguistic validation from automated functional parity checks. For screenshots of a reproduced state, capture the relevant viewport or full page and retain the locale, build, browser, and test data with the artifact.

For broader execution, Selenium Grid runs browser sessions across machines and platform combinations. Use it to add browser or operating-system coverage where those differences matter; keep locale coverage tied to explicit product requirements. See Selenium Grid documentation.

7. Make failures reproducible

Attach the following to each failure report:

  • Locale tag and how the application locale was selected.
  • Browser, browser version, driver, Selenium binding and version.
  • Time zone, operating system, viewport, and whether BiDi emulation was enabled.
  • Application build, test data, journey step, expected value, and observed value.
  • Screenshot or other relevant artifact, plus console or network details when they help explain the failure.

A failure that only occurs with a specific time zone, script, or browser becomes much easier to diagnose when these conditions are recorded explicitly.

8. Troubleshooting

Symptom Likely cause Fix
The page stays in the default language. The app does not use the browser language, or the locale was set after the page loaded. Select locale through the application’s supported mechanism before asserting; reload or restart the journey if required.
BiDi locale or time-zone command fails. Unsupported browser/binding, BiDi not enabled, or a different API signature in the installed version. Check the Selenium API and browser support for the exact versions. Use app-level locale selection for functional tests while resolving emulation separately.
Text assertion fails only in one locale. The test asserts translated copy, a fallback string appears, or copy changed legitimately. Use stable identifiers for behavior. Assert text only when wording itself is the requirement; route translation defects to linguistic review.
Date or currency assertion is inconsistent. Test data or time zone is uncontrolled, or display text was parsed as the underlying value. Fix the instant, explicitly set the intended time zone, and assert stored value and localized rendering separately.
Element cannot be found after switching language. The test locates it by translated text, the page has not finished updating, or the selector is unstable. Use test IDs or another stable selector and wait for a meaningful state transition.
RTL page looks wrong despite passing tests. Functional assertions do not detect visual order, clipping, or mixed-direction problems. Inspect a rendered screenshot and review the layout with someone familiar with the target language.
Grid results differ from local runs. Browser, OS, fonts, time zone, or capabilities differ between nodes. Log environment details, align capabilities where possible, and reproduce on the same browser and platform combination.

9. Performance, reliability, and cost considerations

Running every workflow against every locale and browser can multiply suite time. Prioritize critical journeys and locales that exercise distinct behavior, then expand the matrix where risk calls for it. Reuse test journeys and parameterize locale-specific expectations rather than duplicating entire suites. Parallel execution through Grid can increase throughput, but total run time and reliability still depend on browser startup, application response, test data isolation, and the environment.

Keep waits tied to observable states rather than fixed sleeps wherever possible. Make locale selection explicit at the start of each test so one case cannot leak settings into the next. Use stable fixtures, clean up persisted state, and retry only failures that are known to be transient; retries should not hide deterministic locale defects. Selenium itself does not price or bill localization tests; account for the browser infrastructure and any application environments your suite uses.

Or skip the browser setup

If you already have a reproducible localized page state, ScreenshotNeo can capture it with one API request. It is a website screenshot API and MCP server from Yorker Media. Use Selenium to select the app locale and reach the state you want to inspect; use ScreenshotNeo when you want a screenshot from a URL without managing your own screenshot browser setup. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.test/checkout?locale=fr-CA -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.test/checkout?locale=fr-CA"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.test/checkout?locale=fr-CA'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, and response headers say which page verdict and billing status applied. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does changing Chrome’s language test every localized version?

No. Browser preferences and the application’s locale-selection mechanism are separate. Set both when both are relevant to the product behavior.

Can Selenium confirm that a translation is correct?

No. It can check functional behavior and render states for inspection. A target-language expert must assess accuracy and in-context meaning.

Should I test every supported locale in every browser?

Build the matrix from supported-market requirements and risk. Cover distinct locale behavior and important browser differences without treating a sample locale as representative of all others.