How to Test Translation Failure on Your Website
To test translation failure, reload your translated pages while the translation provider's requests are blocked, returning errors, slow, or cut off by an offline browser, then check that the page still shows readable content and a working language switcher. Do this in Chrome DevTools for a quick manual check, in Playwright for a repeatable one, and in Google's URL Inspection tool to see what a crawler gets. This guide gives the steps and a test matrix.
What are you actually testing?
You are testing the dependency, not the vendor. Your translation layer relies on some set of requests, such as a script, an API call or a translation file. If you do not already know their domains, open the Network panel on a translated page and list every third-party host. Then decide for each failure type what the correct behaviour should be. The usual target is: readable source-language content, no blank regions, no frozen page, a functioning language switcher. The failure modes behind these tests are described in what happens when your translation provider goes down.
How do you block vendor domains in Chrome DevTools?
Chrome's documentation describes the feature as the Request conditions drawer (older Chrome documentation and the page URL call it Network request blocking).
- Open DevTools and a translated page.
- Open the Command menu (Ctrl+Shift+P on Windows, Linux or ChromeOS; Cmd+Shift+P on macOS), type "Request conditions", and select Show Request conditions. You can also reach it through More tools in the three-dot menu.
- Click Add condition and enter a URL pattern. Wildcards work, for example
*://translate-vendor.example.com/*matches requests to that domain. - Tick Enable blocking and throttling.
- Reload. Blocked requests show in red in the Network panel; you can filter to them with More filters and Blocked requests.
Two details from the docs: if a request matches several patterns the first rule wins, and closing DevTools disables blocking while keeping your saved patterns, so reopen the drawer and re-enable it when you return. You can also right-click a request in the Network panel and choose Block request.
This test mimics an ad blocker, a corporate firewall or a vendor domain that is unreachable. Look for untranslated text, errors in the console, a layout that collapses, or a page that waits.
How do you simulate slow responses and offline mode?
In the Network panel, the Throttling drop-down offers presets (fast 4G, slow 4G, 3G), custom profiles under Settings, and Offline. A warning icon appears next to the Network tab while throttling is on. Remember to turn it off afterwards.
Offline mode is useful for testing caching: load the page once online, switch to Offline, and reload. If you rely on a service worker or localStorage cache, translated content should still appear. If it does not, your cache is not doing its job. Also tick Disable cache deliberately for the opposite test, a first visit with nothing cached.
DevTools' throttling slows the whole page, not only the vendor. To isolate one host, use the scripted approach below.
How do you simulate a 500 error from the translation service?
DevTools can edit response headers locally, per Chrome's Network reference, but its page does not describe overriding a status code or file contents, so we do not recommend it for this. A scripted test is cleaner. In Playwright, route.fulfill() answers a request itself, with a status (default 200) and a body, json, headers or contentType. A 503 with a small JSON body is a good stand-in for a vendor error.
Can you script these tests in Playwright?
Yes. Playwright routes are set on a context with context.route() (which also covers popups and opened links) or on a page with page.route(). A route handler can route.abort(), route.fulfill(), or route.continue(). Patterns can be globs, where * does not cross / and ** does, or regular expressions. Here is a compact example using @playwright/test:
import { test, expect } from "@playwright/test";
const VENDOR = "**/translate-vendor.example.com/**"; // replace with your vendor host
const PAGE = "https://staging.example.com/fr/produits/";
test.use({ serviceWorkers: "block" }); // so routes see every request
test("page stays usable when vendor requests are blocked", async ({ context, page }) => {
await context.route(VENDOR, (route) => route.abort("blockedbyclient"));
await page.goto(PAGE);
await expect(page.locator("h1")).toBeVisible();
await expect(page.locator("[data-lang-switcher]")).toBeVisible();
});
test("page stays usable on vendor 503", async ({ context, page }) => {
await context.route(VENDOR, (route) =>
route.fulfill({ status: 503, contentType: "application/json", body: "{}" })
);
await page.goto(PAGE);
await expect(page.locator("h1")).toBeVisible();
});
test("slow vendor does not block rendering", async ({ context, page }) => {
await context.route(VENDOR, async (route) => {
await new Promise((r) => setTimeout(r, 10000)); // 10 s delay
await route.continue();
});
await page.goto(PAGE, { waitUntil: "domcontentloaded" });
await expect(page.locator("h1")).toBeVisible({ timeout: 3000 });
});
test("offline after first load", async ({ context, page }) => {
await page.goto(PAGE);
await context.setOffline(true);
await page.reload().catch(() => {}); // a plain reload may fail without a service worker
// assert whatever your offline design promises
});
Notes, each from Playwright's documentation:
route.abort([errorCode])defaults tofailed; accepted values includeblockedbyclient,connectionrefused,namenotresolved,timedoutandinternetdisconnected. Different codes exercise different failure paths: usenamenotresolvedto mimic DNS problems.context.setOffline(true)emulates a disconnected network for the context, including navigations,fetch()and XHR.- Matching requests stall until your handler continues, fulfils or aborts them, which is how the delay test works.
- Enabling routing disables the HTTP cache, so these tests cannot check HTTP caching behaviour. Test headers separately, for example with
curl -I. - Requests intercepted by a service worker are not routed, hence
serviceWorkers: "block". When you want to test the service worker itself, remove that option and use DevTools' offline mode instead.
The selectors ([data-lang-switcher]) are placeholders for your own markup.
What does Googlebot see during a failure?
Browser tests show what visitors get. For Google, check the rendered HTML:
- Use URL Inspection in Search Console, or the Rich Results Test, to view the rendered HTML of a translated URL. Google's JavaScript documentation names both for this purpose.
- Compare it with the HTML you serve. If translated text exists only after a script runs, expect it to depend on that script succeeding when Google renders.
- Don't count on browser storage. Google documents that its rendering service clears local storage, session storage and cookies across page loads, so a cached translation in the browser will not be present.
- Check robots.txt does not block your translation files. Google does not render JavaScript from blocked files.
- Watch the Crawl Stats report, which Google recommends for monitoring Googlebot and rendering activity, and look for spikes in server errors.
Google's HTTP-errors page says 5xx and 429 responses make its crawlers slow down and that content served with them is ignored. A fault in your translation layer that makes your own pages return 5xx is therefore more serious than one that merely leaves text untranslated. These tools test one URL at a time and cannot reproduce an intermittent outage, so treat them as a spot check. See client-side vs server-side translation and SEO for why delivery method matters.
Test matrix
Run each row on at least one page per language and one per template.
| Scenario | How to trigger | Expected result | If it fails |
|---|---|---|---|
| Vendor script blocked | DevTools Request conditions, or route.abort() |
Source-language page, switcher works | Fix the fallback or remove the dependency |
| Vendor API 500/503 | route.fulfill({ status: 503 }) |
No blank regions, no console exceptions that stop the page | Add error handling and a default |
| Vendor slow (10 s) | Delayed route.continue() |
First paint is not delayed | Load asynchronously; add a timeout |
| DNS failure | route.abort("namenotresolved") |
Same as blocked | Same |
| Offline after first load | DevTools Offline or setOffline(true) |
Behaves as designed (cached or source language) | Review cache strategy |
| Cold cache, first visit | DevTools Disable cache | Page renders with fallback, translations load or not | Check preload and fallback |
| Googlebot view | URL Inspection rendered HTML | Translated or source content present | Move key text into delivered HTML |
| Quota exceeded or lapsed plan | Ask the provider for a sandbox, or simulate with a 402/429 body | Existing pages still show something | Add monitoring and a cached copy |
The last row cannot be fully reproduced without cooperation from the provider, so treat it as a code review item: read how your integration handles non-200 responses.
How do you make this routine?
Put the scripted tests in your continuous integration so a theme update cannot silently remove the fallback. Add a monitor that checks a translated page for expected strings, not only for a 200 status. And run the performance side of the matrix too; the same blocking trick used here is how you measure the cost of the tool, described in translation plugin performance and Core Web Vitals. For the design patterns that make these tests pass, see static translation bundles and CDN failover.
Key takeaways
- Test three failures per vendor dependency: blocked, erroring and slow, plus offline for cached designs.
- DevTools' Request conditions drawer is the quickest manual check; Playwright's
route.abort()androute.fulfill()make it repeatable. - Block service workers in Playwright when using routes, and remember routing disables the HTTP cache.
- Use URL Inspection to see the rendered HTML Google gets, but expect it to be a single-URL spot check.
- Pass criteria are simple: readable content, a working switcher, and a page that does not wait on the vendor.
Sources
- Network features reference (Chrome DevTools) – throttling presets, Offline, blocked-requests filter, header overrides
- Network request blocking (Chrome DevTools) – Request conditions drawer, URL patterns, enabling blocking
- Network (Playwright) – context.route and page.route, abort, fulfill, glob patterns
- Route class (Playwright) – abort error codes and fulfill options
- BrowserContext (Playwright) – setOffline, routing and the service worker and HTTP cache caveats
- JavaScript SEO basics – testing with URL Inspection and the Rich Results Test; blocked resources
Frequently asked questions
How do I simulate a translation provider outage?
Block the provider's domains in your browser's developer tools, or route those requests to an error in an automated test, then reload translated pages. Do it three ways: blocked, returning a 500, and slow. Each shows a different failure, from missing text to a page that hangs.
Can I test what Googlebot sees without waiting for a real crawl?
Partly. The URL Inspection tool in Google Search Console and the Rich Results Test show the rendered HTML Google sees for a page. They test a single URL at a time and do not reproduce an intermittent outage, so combine them with the browser tests in this guide.
Why does my Playwright test not intercept some requests?
A service worker can answer requests before Playwright's routes see them. Playwright's documentation recommends setting serviceWorkers to 'block' when you use request interception. Also note that Playwright documents that enabling routing disables the HTTP cache.
How often should I run these tests?
Run them after any change to your translation setup, theme or CDN configuration, and on a schedule if you can automate them. The scripted checks are cheap to run in continuous integration, whereas manual DevTools checks are best before launches.