Working with Localization

What is Localization?

Webflow Localization is a native, end-to-end solution for customizing your website for visitors around the world --from design to translation to publishing.

For businesses of any size to scale internationally, they need to be able to truly tailor their websites to resonate with global audiences. Localization includes but goes far beyond translation, or simply converting the text on your site to a different language. It means customizing anything from the design to what images you choose to unique content per locale. It also means making sure your site is easily discoverable by the people and prospects in the regions you’re targeting.

How can I use these APIs?

Webflow's localization APIs empower developers to automate and manage the localization process across multiple sites, ensuring consistency and quality. With these APIs, your apps can help users make dynamic content updates and enable custom localization workflows, providing scalability for growing businesses that are looking to enhance global user engagement and optimize performance for international audiences.


In this tutorial, we'll use a mockup site for a fintech application, AstralFund, and walk through the process of localizing content for a French audience. By the end of this tutorial, you'll have a fully localized “Contact Us” page and a new testimonial that resonates with your French audience. Ready to start? Let's dive in!

What You’ll Learn

  • Identifying primary and secondary locales within Webflow.
  • Localizing the DOM elements like text and images.
  • Optimizing SEO data for different locales.
  • Managing CMS content across multiple locales.

What You’ll Need

Localization in Action: AstralFund

AstralFund, an imaginary bank for this example, serves two locales, the United States and France. To properly address each market’s needs, the bank needs to localize content throughout the site. In the example, we’ve localized some content, but we’ll walk through how to localize the entire site in this tutorial.

Primary Locale: United States 🇺🇸
The site's primary locale is set to the United States with content in English.
Secondary Locale: France 🇫🇷
A secondary locale for France is available, with the homepage localized in French. Notice, the localized image and the decimals replaced by commas. However, some content, like the testimonials, still needs to be localized.

Step 1: Clone AstralFund and Identify Localization Opportunities

  • Clone the Example Repository to get the localized example data. There's an full example of all the steps below in index.js. However, if you'd like to follow along with this guide step-by-step create a new file called localization.js with the following imports of the translated content we'll need to localize our site, and the Webflow Javascript SDK. After each step, you can run the file by typing the command node localization to see your progress.
import localizedDOM from "./helpers/Contact Us - French.json" assert {type: "json"}// Localized "Contact Us DOM
import localizedMetadata from "./helpers/seoData.json" assert {type: "json"}// Localized SEO Data
import frenchTestimonials from "./helpers/Testimonials - French.json" assert {type: "json"}// Localized Testimonials
import newTestimonial from "./helpers/newTestimonial.json" assert {type: "json"} // New French Testimonial
import WebflowClient from "webflow-api"
  • Clone the AstralFund site to your Webflow account, and add it to a workspace used for testing.
  • Publish the site to set it live.
  • Navigate to the French locale to see the localized French homepage.
  • Navigate to the Contact page in French. Note the content that is not yet localized. We’ll fix this by localizing the navigation bar, contact content, form, footer, and SEO data.

Step 2: Retrieve Locale Identifiers

In this step we'll retrieve the site and locale identifiers, so that we can make locale specific requests to our site

  • Make sure you have a valid Bearer Key that is authenticated for your new site. You can easily do this by authenticating through our API reference docs. Once you have your Bearer Key, you can store it in your .env file as WEBFLOW_API_TOKEN
    const webflow = new WebflowClient ({accesToken: process.env.WEBFLOW_API_TOKEN });
  • Call the List Sites endpoint to find your siteId and locale information

  • Extract the localeId for both English and French from the Site object

    • Notice the locales parameter, which returns a primary locale, and an array of secondary locales
    • Each locale has useful information like the language, location, and more.
    • In addition to a specific localeId, each locale also has a cmsLocaleId
      Store these IDs as variables for later use.
  • Store these IDs as variables for later use.

// List sites and get the Astral Fund site's details
const sites = await listSites();
const astralFundSite = sites.find(site => site.displayName.includes("AstralFund"));
const siteId =;
const siteDetails = await getSiteDetails(siteId);

// Extract and store locale IDs
const locales = siteDetails.locales;
const secondaryLocaleId = locales.secondary[0].id; // French is the first secondary locale
const secondaryCmsLocaleId = locales.secondary[0].CmsId
console.log([locales, secondaryLocaleId, secondaryCmsLocaleId])

Step 3: Localize Page Content and SEO Data

In this step, we're getting the content and metadata from a static, primary page, and uploading a translated version to our locale-specific page.

  • Get the page_id of the Contact Us page using the List Pages endpoint
   // Get the Page Info for "Contact Us"
    const pages = await listPages(siteId)
    const contactPage = pages.find(page => page.title.includes("Contact"));
    const contactPageId =

  • Get the content of the Primary Locale using the Read DOM endpoint. This will return all localizable content from a static page, which we can then translate for our locale-specific page.


As of Sep 22, 2023 , we only support writing to Text and Rich Text to the DOM. We do not support updating images via this API yet.

  • Modify the content to include localized versions of the nav bar, contact content, form, and footer. We’ve provided a localized DOM for you with ./helpers/Contact Us - French.json
  • Update the content of the french locale by making a POST request to the Update DOM endpoint, entering the localeId in the locale query parameter.
    // Get the DOM for the Contact Us page in English and translate to French
    const primaryContactPageDom = await getDOM(contactPageId);

    // Update the Contact Us page DOM with French content
    await updateDOM(contactPageId, localizedDOM, secondaryLocaleId);

Now, let's get page metadata to update the SEO and OpenGraph data

  • Retrieve the primary page's SEO data via a GET request to the Get Page Metadata endpoint
  • Translate the data so that it's relevant for the French audience. We’ve provided localized information for you with ./helpers/seoData.json
  • Update the SEO Data for the french locale' via a POST request to Update Page Metadataendpoint. Be sure to enter the localeId in the locale query parameter.
    // Get page metadata with localized SEO data
    const pageMetadata = await getPageMetadata(contactPageId);
    const frenchMetadata = await updatePageMetadata(contactPageId, localizedMetadata);

Step 4: Manage Testimonials with the CMS

To demonstrate AsrtralFund’s commitment to the French market, we'll translate the existing testimonials, and create a French-specific testimonial from a French regulatory authority.

  • Get existing testimonials and translate them using our provided translation.
  • For each translated testimonial, update the CMS item via the Update Collection Item endpoint. Be sure to include cmsLocaleId in the body of the request. If you're using our translated data, one of the testimonials will be set to draft, so that we can highlight the French-only testimonial that we'll create in the next step.
    // Work with CMS data for testimonials
    const collections = await getCmsCollections(siteId);
    const testimonialsCollectionId = collections.find(collection => collection.displayName === 'Testimonials').id;
    const testimonials = await getCmsItems(testimonialsCollectionId);

    // Translate Testimonials, setting the first one to draft
    const localizedItems = await updateLocalizedCmsItems(testimonialsCollectionId, frenchTestimonials, secondaryCmsLocaleId)

  • Create a French-only testimonial using our provided translation.
// Create a French-Only Testimonial
const newTestimonial = await createFrenchTestimonial(testimonialsCollectionId, newTestimonial, secondaryCmsLocaleId);

Step 5: Appreciate your beautifully localized site! 👏