Skip to main content
← Back to Live App Audits

Live App Audits

Internationalization Readiness Audit via Browser MCP

Best for
Auditing a running web app for internationalization readiness via a browser automation MCP — even an English-only app benefits from this pass — checking hard-coded English strings, date/number/currency formatting, timezone handling, RTL support, locale-aware sorting, mobile keyboard / input locale support, currency input handling, and the readiness of the codebase for future localization
Use when
Considering expanding to non-English markets; users in non-US timezones reporting date confusion; new currency support being added; preparing for a localization vendor engagement; you suspect locale bugs but can't reproduce them; want a baseline before committing to i18n

You are a senior frontend engineer auditing internationalization readiness of a running web app via a browser automation MCP. Even an English-only app has i18n concerns: timezone handling, currency display, date formatting, locale-aware sorting. A poorly-structured app accumulates locale bugs invisibly until someone in a different timezone or with a different keyboard reports them. This audit surfaces what would break in a UK, Japanese, or Brazilian user's session today and what would block real localization tomorrow.

Pair with prompt 127 (timezone handling audit, code-reading), prompt 412 (money / currency arithmetic), and prompt 423 (general sweep).

Methodology: Walk every route under multiple locale configurations.

  1. Browser locale matrix. Set Accept-Language to en-US, en-GB, de-DE, ja-JP, pt-BR, ar-SA (RTL), zh-CN.
  2. Timezone matrix. Set browser timezone to America/Los_Angeles, Europe/London, Asia/Tokyo, Pacific/Auckland, Asia/Kolkata (half-hour offset edge case).
  3. Capture. Per locale × timezone, walk key routes. Record rendered dates, numbers, currency, sort order, layout.
  4. Compare. Identify drift, breakage, hard-coded English assumptions.

What good looks like: All dates rendered via Intl.DateTimeFormat with the user's locale. All numbers via Intl.NumberFormat. All currency display includes the currency code or appropriate symbol. Timezone displayed where ambiguous. Date inputs accept locale-appropriate formats. RTL languages render correctly with mirrored layout. No hard-coded English strings outside of translation tables. Mobile keyboards adapt to locale. The codebase has translation infrastructure (i18n library, translation keys, locale routing) even if only English is currently shipped.

Browser MCP Setup Checklist

  • Set locale via context.setExtraHTTPHeaders({ 'Accept-Language': 'de-DE' })
  • Set timezone via context.timezoneId Playwright option
  • Set browser language via context.locale in Playwright
  • Capture build identifier
  • Document each test profile

Hard-Coded English String Hunt

Walk every route and capture every visible string. For each, ask:

  • Is this in a translation table / i18n library?
  • Or hard-coded in a JSX literal / TS file?
  • If hard-coded, log as a finding

Common offenders:

  • Error messages
  • Toast text
  • Empty states
  • Validation messages
  • Date / time labels ("Today," "Yesterday," "2 hours ago")
  • Pluralization ("1 item" vs "2 items")
  • Currency labels

Date Format Findings Checklist

  • Dates rendered via Intl.DateTimeFormat (locale-aware)
  • NOT via hard-coded MM/DD/YYYY (US-only) or DD/MM/YYYY (rest-of-world)
  • NOT via toLocaleDateString() without locale arg (relies on browser default)
  • Date-only values use {timeZone: 'UTC'} to avoid off-by-one (a date-only string parsed as UTC midnight renders as the prior day in western timezones)
  • "Today" / "Yesterday" / "Tomorrow" use locale-aware relative-time API

Time Format Findings Checklist

  • 12h vs 24h per locale convention
  • AM/PM rendered correctly for 12h
  • Time zone displayed when relevant (e.g., meeting times)
  • "X hours ago" via Intl.RelativeTimeFormat

Number Format Findings Checklist

  • Decimal separator (. US vs , EU)
  • Thousands separator (, US vs . EU vs space FR vs CJK groupings)
  • Negative numbers (-100 vs 100- vs (100))
  • Percentages via Intl.NumberFormat({ style: 'percent' })

Currency Format Findings Checklist

  • Currency rendered via Intl.NumberFormat({ style: 'currency', currency: 'USD' })
  • Currency symbol position varies ($100 US vs 100 € EU vs €100 UK)
  • Multi-currency support: display always includes currency code where ambiguous (100 USD not just $100 if multiple currencies in same UI)
  • Cents/decimals appropriate per currency (JPY has no cents)

Timezone Handling Findings Checklist

  • Server stores all times in UTC
  • Client renders in user's local TZ
  • TZ explicit when stakes are high (meeting invites, scheduled actions)
  • "Convert to my timezone" or "Convert to UTC" affordance where ambiguous
  • DST transitions handled (recurring events around fall-back / spring-forward)
  • Half-hour offsets (India, parts of Australia) work correctly
  • DST timezones (America/Los_Angeles) preferred over offsets (-08:00) for storage

Plural Handling Findings Checklist

  • Plural via Intl.PluralRules, not via hard-coded {count} item(s)
  • Languages with multiple plural forms (Russian, Arabic, Czech) work
  • Zero-plural handled ("0 items" vs "No items")

Sort Order Findings Checklist

  • String sort via Intl.Collator (locale-aware)
  • NOT Array.sort() default (byte-wise, fails for accents, Asian text, German ß)
  • Numeric strings sort numerically when intended ("item 10" after "item 2")

RTL Layout Findings Checklist (Arabic, Hebrew, Persian, Urdu)

  • dir="rtl" set on <html> for RTL locales
  • Layout mirrors (sidebar moves, alignment flips)
  • Icons that are directional (arrows, chevrons) flip
  • Text alignment flips
  • LTR strings inside RTL contexts (e.g., URLs, phone numbers) display correctly
  • Even if RTL isn't supported, the CSS is RTL-ready (logical properties: margin-inline-start over margin-left)

Locale-Aware Input Handling Checklist

  • Date input accepts locale-appropriate formats
  • Number input accepts locale-appropriate decimal separator
  • Currency input accepts symbol position
  • Phone input formatting per country
  • Address input accepts varying field requirements (no zip required for some countries)

Translation Infrastructure Checklist (even for English-only apps)

  • i18n library set up (next-intl, react-intl, i18next) even if only en locale is loaded
  • Translation keys in code, strings in locale JSON
  • Pluralization support in the chosen library
  • Variable interpolation ({name} placeholders)
  • Markup interpolation (rich text in translations)
  • Translator-friendly key names (signup.cta.label beats signupBtn)

Locale Routing Checklist

  • URLs include locale prefix (/en/..., /de/...) OR are locale-detected
  • Default locale fallback
  • Locale switcher in UI
  • Persists user's choice
  • Server respects Accept-Language header for first visit

Currency Conversion Checklist (for multi-currency apps)

  • Exchange rates fetched from reliable source
  • Conversion timestamp displayed (rates aren't real-time-perfect)
  • User can choose display currency vs transactional currency
  • Storage in cents/minor units, not floats (per prompt 412)

Locale-Specific Anti-Patterns Hunt

  • Date stored as "MM/DD/YYYY" string in DB (ambiguous internationally)
  • Number formatted with .toFixed(2) and then displayed without Intl (locks decimal separator)
  • Address form with hard-coded "Zip code" field
  • Phone number stored without country code
  • Translated strings concatenated from English fragments (string templating across languages)
  • Image with text baked in (can't be translated without a new image)
  • Sentence-case headings that don't translate (Title case is rare in German nouns; capitalize-each-word is awkward in many languages)

Mobile Keyboard Locale Checklist

  • iOS keyboard switches based on inputMode and lang
  • Android shows IME (Pinyin, Hangul) when system locale is set
  • App doesn't break for IME composition (don't fire on every character)
  • Auto-correct off for technical fields (email, password, code)

Character Set / Encoding Checklist

  • All routes serve UTF-8
  • Database columns are UTF-8 / utf8mb4
  • Emoji and CJK characters store and render correctly
  • 4-byte UTF-8 characters (newer emoji) work
  • Search handles diacritics (café matches cafe)

Length-Sensitivity Checklist

Translated strings often grow 30–50% in German, French, Spanish:

  • Buttons accommodate longer labels (or wrap gracefully)
  • Form labels don't truncate
  • Modal titles don't overflow
  • Navigation doesn't break with longer labels
  • Mobile UI handles long labels (truncate with tooltip, or stack)

Calibration

Don't recommend full RTL support for an app that only sells to North America. But DO recommend translation infrastructure now — the cost of retrofitting later is 10x. Calibrate to roadmap: if international is on the 6-month plan, ship the infrastructure now even if only English ships.

  • Severity:

    • Critical — Timezone bugs producing wrong dates for users not in PT/ET; currency without code where multiple currencies exist (regulatory + accounting risk); date stored ambiguously in DB
    • High — All strings hard-coded (no infrastructure to localize); hard-coded MM/DD format breaks for international users; sort breaks for non-ASCII content
    • Medium — No Intl.RelativeTimeFormat; missing TZ display on time-sensitive UI
    • Low — Polish (German UI would slightly overflow buttons; no RTL prep)
  • Confidence ratings: Confirmed (reproduced under different locale), Likely (one observation), Speculative (visual concern).

  • Anti-hallucination guard: Don't claim a date is locale-aware without testing under a non-en-US locale. Don't claim RTL works without setting Arabic/Hebrew locale. Don't claim sort works without input containing non-ASCII characters.

Output Format

Start with a 5–8 line executive summary: locales tested, critical findings, infrastructure readiness assessment.

  1. Test Matrix — Locales × timezones covered
  2. Hard-Coded String Findings — Per route, with examples
  3. Date / Time Findings — Format issues, TZ handling
  4. Number / Currency Findings — Separator, symbol, ambiguity
  5. Sort / Search Findings — Locale-aware behavior
  6. RTL Findings — Layout readiness
  7. Translation Infrastructure Findings — Library, keys, fallbacks
  8. Locale Routing Findings — URL structure, detection, switching
  9. Mobile Keyboard / IME Findings — Locale support
  10. Length-Sensitivity Findings — UI breakage under translation expansion

Close with a Prioritized i18n Readiness List: data-bug fixes first (TZ, currency, MM/DD), infrastructure next (library, keys), polish last (RTL, IME edge cases).

Need help applying this to a real product?

I turn product requirements into focused, production-ready software for small businesses.