Working with Localization
Webflow Localization is end-to-end solution for customizing your website for visitors around the world – from design to translation to publishing. With these APIs, your Apps can 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.
Let's look at an example. AstralFund is an imaginary bank that 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 images below, we’ve localized some content. In this tutorial, we’ll walk through how to localize the entire site.
United States 🇺🇸
The site's primary locale is set to the United States with content in English.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.What we'll build
In this tutorial, we'll walk through the process of localizing content for a French audience on a website. 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. You'll learn how to:
- Identify primary and secondary locales within Webflow.
- Localize the DOM elements like text and images.
- Optimize SEO data for different locales.
- Manage CMS content across multiple locales.
Prerequisites
- Astral Fund Cloneable
- Our Localization Example with code samples and localized data
- A Webflow site plan that supports CMS
- A Webflow App or a Site Token with the following scopes:
sites:read
,cms:read
, andcms:write
- Some knowledge of HTTP requests and JavaScript
- 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.
- Clone the Example Repository
Clone the example repository and install dependencies.
# Clone the example repository git clone https://github.com/Webflow-Examples/Localization-Demo.git cd localization-demo # Install dependencies npm install
- Make sure you have a valid Bearer Key that is authenticated for your new site. You can do this by authenticating through our API reference docs. Once you have your Bearer Key, you can store it in your
.env
file asWEBFLOW_API_TOKEN
-
There's a full example of all the steps below in
index.js
. However, if you'd like to follow along with this guide, create a new file calledlocalization.js
, and include the following imports of the translated content, as well as the Webflow Javascript SDK.import localizedDOM from "./helpers/Contact Us - French.json" assert {type: "json"};// Localized "Contact Us" DOM import localizedMetadataBody from "./helpers/seoData.json" assert {type: "json"};// Localized SEO Data import frenchTestimonials from "./helpers/Testimonials - French.json" assert {type: "json"};// Localized Testimonials import newFrenchTestimonial from "./helpers/newTestimonial.json" assert {type: "json"};// New French Testimonial import { WebflowClient } from "webflow-api"; import dotenv from "dotenv"; - Create an asynchronous function, and initialize the API using the Webflow Javascript SDK:
async function run() { try { // Initialize the API. dotenv.config(); const token = process.env.WEBFLOW_API_TOKEN; const webflow = new WebflowClient({ accessToken: token }); /* ADD CODE FROM GUIDE HERE */ } catch (error) { console.error("An error occurred:", error); } } run();
After each step, you can run the file by typing the command
node localization
to see your progress.
- Call the List Sites endpoint to find your
siteId
andlocale
information. Replace thesiteName
variable with the name of your cloned site.// List sites and get the Astral Fund site's details const siteName = "AstralFund" // Change the site name to the name of your cloned site const sites = await webflow.sites.list(); const astralFundSite = sites.sites.find((site) => site.displayName.includes(siteName) ); const siteId = astralFundSite.id; const siteDetails = await webflow.sites.get(siteId); // Get site details for locale information - Extract the
localeId
for both English and French from the Site object:- Notice the
locales
parameter, which returns aprimary
locale, and an array ofsecondary
locales. - Each locale has useful information like the language, location, and more.
- In addition to a specific
localeId
, each locale also has acmsLocaleId
.
// 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].cmsLocaleId; console.log([locales, secondaryLocaleId, secondaryCmsLocaleId]); - Notice the
- Get the
page_id
of the Contact Us page using the List Pages endpoint// Get the page information for "Contact Us" const pages = await webflow.pages.list(siteId); const contactPage = pages.pages.find((page) => page.title.includes("Contact") ); const contactPageId = contactPage.id; - 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
Then create a DOM write object, with an array of DOM Nodes and thecmsLocaleId
- Update the content of the French locale by making a
POST
request to the Update DOM endpoint, entering thelocaleId
in thelocale
query parameter.// Get the DOM for the Contact Us page in English and translate to French const primaryContactPageDom = await webflow.pages.getContent(contactPageId); // Create the domWrite object with the nodes and cmsLocaleId const domWrite = { nodes: localizedDOM.nodes, locale: secondaryLocaleId, }; // Update the Contact Us page DOM with French content await webflow.pages.updateStaticContent(contactPageId, domWrite);
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 the Update Page Metadata endpoint. Be sure to enter thelocaleId
in thelocale
query parameter.// Get page metadata with localized SEO data const pageMetadata = await webflow.pages.getMetadata(contactPageId); // Create Localized Page Setting Request const localizedMetadata = {}; localizedMetadata.locale = secondaryLocaleId; localizedMetadata.body = localizedMetadataBody; // Update SEO Data await webflow.pages.updatePageSettings(contactPageId, localizedMetadata);
- Get existing testimonials and translate them using our provided translation.
// Get Collections const collectionsData = await webflow.collections.list(siteId); const collections = collectionsData.collections; // Find Testimonials Collection const testimonialsCollectionId = collections.find( (collection) => collection.displayName === "Testimonials" ).id; const itemsData = await webflow.collections.items.listItems( testimonialsCollectionId ); const items = itemsData.items; // Get item data from testimonial collection
- For each translated testimonial, update the CMS item via the Update Collection Item endpoint. Be sure to include cmsLocaleId in the Item.
try { // For each CMS item for (const [index, value] of items.entries()) { // Add the secondary `cmsLocaleId` to the item frenchTestimonials[index].cmsLocaleId = secondaryCmsLocaleId; // Update the CMS item const updatedItem = await webflow.collections.items.updateItemLive( testimonialsCollectionId, value.id, frenchTestimonials[index] ); console.log(`Item:`, updatedItem); } } catch (error) { console.error(`Error updating CMS items:`, error); throw error; }
- Create a French-only testimonial using our provided translation.
// Create new item try { // Set the `cmsLocaleId` of the new item newFrenchTestimonial.cmsLocaleId = secondaryCmsLocaleId; const newTestimonial = await webflow.collections.items.createItem( testimonialsCollectionId, newFrenchTestimonial ); console.log("Localization process completed successfully."); } catch (error) { console.error("Error Creating CMS Item:", error); }
Congratulations! You've localized your AstralFund site! Take a look around the site and see what other opportunities you have to localize content.
United States 🇺🇸
The site's primary locale is set to the United States with content in English.
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.
Updated 7 days ago