· Elias Salem · Puppeteer, Automation  · 3 min read

Working with localized content in Puppeteer

How to access localized content in Puppeteer

How to access localized content in Puppeteer

Localized content is essential for providing a tailored user experience to global audiences. Whether it’s adapting text, formatting dates, or displaying region-specific data, localization plays a critical role in user satisfaction.

While working on a feature to allow capturing screenshot on localized pages, we realized that implementing a comprehensive solution often requires combining multiple techniques.

In this guide, we’ll explore how Puppeteer can help test websites with both server-side and client-side localization. We’ll discuss key configurations, including setting HTTP headers, emulating geolocation, and handling websites that rely on client-side rendering for localized content.

Types of Localization in Websites

When testing localization, it’s important to understand the two main ways websites render localized content:

1. Server-Side Localization:

  • The server determines the user’s language and regional settings based on HTTP headers, cookies, or geolocation.
  • Examples: Bing, Google, and other search engines.
  • Puppeteer can test this by setting headers and geolocation.

2. Client-Side Localization:

  • Localization occurs in the browser using JavaScript. The site may fetch user preferences from the browser or an API call.
  • It often relies on the navigator.language property to determine the user’s language.

For websites with client-side localization, you need to simulate user behavior accurately, ensuring Puppeteer interacts with JavaScript-rendered content.

How to Set Browser Language in Puppeteer

In Puppeteer, you can manipulate language settings at least three different ways to target both server-side and client-side localization. These methods include:

  • CLI Argument: Use --lang to set the default language.
  • HTTP Headers: Set the Accept-Language header.
  • Overriding navigator.language: Modify language properties directly.

Implementing all three methods ensures that your browser language is set correctly and increases your chance that the website will display the correct language.

While setting the Accept-Language header works for server-side language detection, overriding navigator.language ensures client-side compatibility. A combination of these methods offers better results.

Here’s a script that set the browser language using all the three methods mentioned:

import puppeteer, { Page } from 'puppeteer';

(async () => {
  const locale = 'fr-FR';
  // Launch Browser with French locale
  const browser = await puppeteer.launch({
    headless: false,
    args: [`--lang=${locale}`],
  });
  const page = await browser.newPage();
  // Set locale to French (For websites using client-side localization)
  await page.evaluateOnNewDocument((locale) => {
    Object.defineProperty(navigator, 'userLang', {
      get: () => locale,
    });
    Object.defineProperty(navigator, 'language', {
      get: () => locale,
    });
    Object.defineProperty(navigator, 'userLanguage', {
      get: () => locale,
    });
  }, locale);
  // Set Accept-Language header (For websites using server-side localization)
  await page.setExtraHTTPHeaders({
    'Accept-Language': locale,
  });
  // Navigate to a website
  await page.goto('https://browserleaks.com/javascript');
  // Capture a screenshot
  await page.screenshot({ path: 'browserleaks-screenshot.png', fullPage: true });
  await browser.close();
})();

How Does It Work?

Here’s a quick breakdown of the code:

  1. The --lang argument sets the browser’s language preferences, ensuring the website renders content according to the specified locale (fr-FR).
  2. Overriding properties like navigator.language, navigator.userLang, and navigator.userLanguage with the desired locale ensures that client-side scripts relying on these browser properties render content in the specified language.
  3. Finally, the header Accept-Language header ensures the server receives the desired locale (locale) as part of the HTTP request, influencing server-side content rendering to provide the appropriate localized content.

While it might seem sufficient to rely solely on setting the HTTP header, our experience has shown that a more robust and generic solution—combining all three methods—yields consistently better and more reliable results.

Back to Blog

Related Posts

View All Posts »