ScreenshotNeo

BlogHow-to

How to Handle Internationalization Testing with Selenium WebDriver

Test translated interfaces, right-to-left layouts, Unicode input, and locale-sensitive values with Selenium WebDriver using a practical coverage plan and runnable examples.

By the ScreenshotNeo team4 October 20268 min read

Direct answer: Use Selenium WebDriver to exercise real browser flows for representative supported locales, scripts, and user journeys. Assert what users can observe: the page language and direction, translated content, Unicode input and output, and locale-sensitive dates, numbers, and currency. Keep selectors stable across translations, then run priority cases across the browsers and operating systems your product supports. Selenium drives the browser; your product requirements define what correct localization means.

A passing browser test is evidence about the paths and outputs it exercised. It does not prove that every translation workflow, database, email, or downstream integration handles every language correctly. Pair browser checks with page-level diagnostics and appropriate backend tests.

1. Define the coverage matrix

Start with the locales and environments the product claims to support. Choose combinations according to user impact, release risk, and known rendering or input differences. Avoid an unbounded locale-by-browser-by-operating-system Cartesian product: a carefully selected matrix gives useful coverage without making every change slow.

Dimension Choose Example questions
Locale Supported language tags and regional variants Are language selection and regional formatting both covered?
Script and direction Writing systems in use, including RTL where supported Does the page set and render direction correctly?
Journey High-value routes and user actions Do navigation, forms, errors, and confirmation states translate?
Browser and OS Environments supported for users Are input, font rendering, and layout differences represented?
Data Representative Unicode and formatted values Do submitted characters and localized dates or amounts survive the flow?

One locale switch does not test every internationalization behavior. Include cases that exercise text expansion, right-to-left layout, accented characters, non-Latin scripts, and mixed-direction content when those are part of your supported product.

2. Set up Selenium WebDriver

The following Python example uses Selenium 4 and Chrome. Install the binding with python -m pip install selenium. Selenium Manager can obtain a suitable driver for common local setups; for controlled CI, provision browser and driver versions using your environment’s established process. Exact browser locale configuration is browser-specific, so this example changes the application locale through a representative user-facing selector rather than relying on unverified emulation flags.

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

options = webdriver.ChromeOptions()
# In CI, add your environment's normal headless option if required.
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)

try:
    driver.get("https://example.test/settings/language")
    locale_select = wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "[data-testid='locale']"))
    )
    Select(locale_select).select_by_value("ar")

    wait.until(lambda d: d.find_element(By.TAG_NAME, "html").get_attribute("lang") == "ar")
    html = driver.find_element(By.TAG_NAME, "html")
    assert html.get_attribute("dir") == "rtl"

    heading = wait.until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='page-heading']"))
    )
    assert heading.text == "العنوان المتوقع"
finally:
    driver.quit()

Replace the example URL, test IDs, locale value, and expected text with your application’s actual contract. Keep expected translations in maintained test data or resource fixtures so reviewers can see why each string is expected. Selenium’s WebDriver is the browser-control layer: the Selenium documentation describes it as driving a browser natively, while the W3C WebDriver standard specifies a platform- and language-neutral remote-control protocol intended primarily for automated browser testing.

3. Assert language, direction, and translated behavior

For each selected route and locale, assert relevant observable behavior. The W3C Internationalization Checker identifies encoding, language declarations, and text direction as key page settings; it can help diagnose a page separately from an end-to-end flow.

html = driver.find_element(By.TAG_NAME, "html")
assert html.get_attribute("lang") == expected_lang
assert html.get_attribute("dir") == expected_direction

# Locate controls through stable hooks; verify their localized labels separately.
submit = driver.find_element(By.CSS_SELECTOR, "[data-testid='submit-order']")
assert submit.accessible_name == expected_submit_label

Use the mechanism your Selenium binding and application expose to inspect accessible names; if it is not available in your chosen binding version, assert the associated label element’s text and relationship instead. Check translated navigation, field labels, validation messages, empty states, and confirmation content as applicable. For RTL pages, test direction declarations and visible alignment or ordering that are part of the product’s design contract.

4. Keep selectors stable across languages

Do not make translated phrases the only way tests locate controls when the application provides a stable test identifier or semantic hook. A translation edit should fail a content assertion when the expected copy changes, not cause unrelated controls to become undiscoverable. Follow the application’s accessibility conventions and assert labels, roles, and visible text independently from element targeting.

# Stable target, separate localized-content assertion
save_button = driver.find_element(By.CSS_SELECTOR, "[data-testid='save-profile']")
label = driver.find_element(By.CSS_SELECTOR, "label[for='display-name']")
assert label.text == expected_display_name_label
save_button.click()

5. Test Unicode through real user flows

Unicode checks should enter text through the same visible form path a user takes, submit it, and verify what the application presents afterward. Unicode guidance recommends UTF-8 for web pages and consistent encoding for multilingual data. Select representative characters from supported locales, including combining marks or mixed scripts if users can enter them.

sample = "Zoë — 東京 — مرحبا"
field = wait.until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='display-name']"))
)
field.clear()
field.send_keys(sample)
driver.find_element(By.CSS_SELECTOR, "[data-testid='save-profile']").click()

shown = wait.until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='saved-display-name']"))
)
assert shown.text == sample

This verifies the exercised browser-to-application path and displayed result. If persistence, exports, email, APIs, or integrations matter, add checks at those boundaries as well; a browser observation alone cannot establish that every downstream system preserves the text.

6. Check locale-sensitive values

Assert user-visible dates, numbers, and currencies using the product’s specified locale behavior. Avoid ambiguous date fixtures such as 03/04/2026 unless the point of the test is to distinguish interpretations. Prefer explicit expected output per locale and test both display and any locale-neutral submitted or stored representation that the application exposes. W3C style guidance recommends locale-neutral data values and unambiguous dates.

# Example contract assertions; expected strings are product-specific.
assert driver.find_element(By.CSS_SELECTOR, "[data-testid='invoice-date']").text == expected_date
assert driver.find_element(By.CSS_SELECTOR, "[data-testid='total']").text == expected_currency

7. Run the matrix efficiently

Run a small high-priority set on each pull request and a broader supported matrix on a scheduled or release run. Selenium Grid distributes browser sessions and supports scaling across browser and operating-system combinations. Use parallel sessions only to the extent your infrastructure can support them, and keep test data isolated so concurrent locale runs do not overwrite each other.

  • Tag tests by locale, script, journey, and environment so failures can be routed and rerun narrowly.
  • Keep browser and binding versions visible in CI output to make environment-specific failures diagnosable.
  • Capture screenshots, page source, console output, and relevant network diagnostics when a run fails, subject to your data-handling rules.
  • Use Selenium WebDriver BiDi only when the specific browser and binding feature you need is available in your selected versions; Selenium describes BiDi event support for network, console, and JavaScript errors as limited and evolving.

8. Add a complementary internationalization diagnostic

Run the W3C Internationalization Checker against deployed or preview pages to inspect markup and HTTP headers for encoding, language declarations, direction, and related suggestions. It complements Selenium: the checker examines page-level settings, while your browser test exercises user journeys and application behavior. Neither one by itself validates your full translation process or every data boundary.

9. Troubleshooting

Symptom Likely cause Fix
Control lookup fails only in one locale The test targets translated text or locale-dependent structure Use a stable test identifier or semantic hook, then assert localized copy separately.
Text appears as replacement characters Encoding is inconsistent in the page or an exercised data boundary Inspect response headers and document encoding; use UTF-8 consistently, then test the submit and return path.
RTL text is present but layout is wrong Direction was not set or the layout has an untested directional assumption Assert the page direction and add focused layout assertions for supported RTL routes.
Date or currency assertion differs by machine The test relies on ambient browser or OS locale settings Make locale setup explicit in the product flow or controlled environment and assert the documented output.
Test passes locally but fails in CI Browser, driver, fonts, locale, timing, or environment differs Record versions and environment; wait for a meaningful condition rather than sleeping a fixed duration.
Unicode field assertion passes but saved data is corrupted elsewhere The test checks only the browser-visible segment Add API, persistence, export, or integration checks at the relevant boundary.
Parallel locale runs interfere Shared accounts or test records are mutated concurrently Isolate fixtures per session or serialize the conflicting journey.

10. Performance, reliability, and cost

Internationalization coverage can multiply execution time when every locale runs on every browser and operating system. Prioritize combinations based on supported environments and user impact, run focused checks early, and distribute broader runs with Grid where available. Use explicit waits for page state and keep fixtures deterministic; fixed delays and shared mutable data create slow, flaky runs.

The relevant execution cost is the browser capacity and maintenance required by your chosen matrix. The research sources establish Selenium Grid as a scaling option but provide no comparative pricing or performance benchmark, so estimate from your own environment. Keep the matrix bounded and revisit it when support commitments, usage, or release risk changes.

Or skip the browser setup

If your immediate task is capturing a localized page for review or documentation, ScreenshotNeo is a website screenshot API and MCP server. It does not replace Selenium assertions for interactive behavior, but it can return a page capture with one request. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/fr -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com/fr"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/fr' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo accepts cookie or 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, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

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

FAQ

Does Selenium decide whether a translation is correct?

No. Your product requirements and reviewed expected outputs define correctness. Selenium exercises the browser and checks observable behavior.

Should every locale run on every browser?

Only if your risk and capacity justify that matrix. Prioritize supported, high-impact combinations and expand coverage for known differences.

Can a browser test prove multilingual data is safe end to end?

It proves only the path and boundaries it checks. Add service, storage, export, or integration checks where those systems are in scope.

When should I use the W3C Internationalization Checker?

Use it to inspect page markup and HTTP headers for internationalization settings alongside, not in place of, Selenium user-flow tests.