Prerequisites
Before completing this guide, make sure you have a solid understanding of Yext Search configuration and frontend implementation. Review the Search Backend and Search Frontend Theme documentation if you haven't already.
What is a Multi-Language Search Experience?
If your website is in a single language, you don't need this guide - just build a standard Search experience. If your website is in two or more languages, you'll want to make sure your customers can search in every language you support.
Multi-language Search allows you to build an experience that can answer questions using content from multi-language profiles in the Knowledge Graph, with a frontend powered by multi-language Pages infrastructure.
As you may recall, a Search experience is composed of:
- A backend Search configuration that determines what data gets surfaced
- A frontend that determines what search results look like
- Data from the Yext Knowledge Graph

Each of these can be configured to work with multiple languages:
- The configuration backend allows you to add
localizationsfor language-specific synonyms or prompts, or you can create separate Search Configurations per language. - The frontend contains a
locale_config.jsonfile with a locale that's passed to the Search JavaScript Library and Theme, allowing you to manage your languages out of a single repository. - The data is indexed and searched based on the specified locales as stored in Content in language profiles.
A singular Search experience can't detect and surface results for multiple locales. You'll be creating separate search pages for each language you want to support.
Note: In this guide, "locale" and "language" (and "locale code" / "language code") are used interchangeably.
Do All Languages Need to Surface the Same Content?
No. We expect there to be variations and have built tools to accommodate this.
Your Search experience can differ by language in terms of:
- Verticals included, as well as vertical configuration like which fields are searchable or the saved search filter
- Other Search Configuration features like Synonyms or Query Suggestions
- Result cards
- Frontend components like facets or sorting
Profile Language Consistency
While your languages can have different verticals, it's important that your language profiles be consistent for your entities so all entities have the same "variation" of a language. If you want just one English experience, make sure they all share the same language code (all "en" or all "en_US"). Each language experience is strictly limited to a locale.
That said, it is fine to have a "jagged language profile structure." You can have some FAQs that have English, Spanish, and French profiles and other FAQs that just have Spanish profiles. The consistency only matters to the extent that they are the same type of Spanish profiles. A jagged structure will simply result in a different number of pages or result cards in each language.
Multi-Language Search Configuration
Your Three Options
When building a multi-language Search experience, you have three backend options:
Option 1: Use one Search Configuration for all languages
Create a single Search Configuration that manages verticals, query rules, synonyms, etc. for all languages. This only works if your experiences are exactly the same across all languages in terms of verticals. Add the appropriate language codes in the "localizations": {} property using the language code from the Knowledge Graph. You can modify synonyms and query suggestions by locale, but not the verticals themselves.
Option 2: Use separate Search Configurations by language (recommended)
Create a separate single-language Search Configuration for each language. This gives you the most flexibility and the least complexity when making updates - you can add, remove, or update verticals for each language at separate times, which is important if content or translations are not all available concurrently. The configuration file is also easier to manage. This is the recommended approach in most cases.
Option 3: Use the same configuration for some languages, but separate configurations for others
Combine Options 1 and 2. For languages that are very similar (especially language variations like en, en_US, en_GB), use the same configuration. For other languages, use separate configurations.
Choosing Your Approach
If your languages will be exactly the same except for language-specific details like synonyms or query suggestions, and the data for each language will be available or updated simultaneously, use Option 1.
If your languages might have variation in terms of which verticals are included, or data for each vertical will be added or updated out of sync, use Option 2. In most cases, Option 2 will be the right one.
If some of your languages are exactly the same but others will be different, use Option 3.
You can use the JSON editor to easily copy and paste configuration between experiences. Access it by clicking "Edit as JSON" under the Configuration navigation.
When building a multi-language experience, build one Search Config first in your primary language, then copy that config for any additional languages (create a new one and copy the JSON code into it, except the name property). Once copied, update properties like the name or vertical names, translate the synonyms and hardcoded prompts, and update any relevant query rules tied to language.
Option 1 - Shallow Merging Details
If you choose Option 1, any language-specific properties must be specified by locale in the localizations array. If you don't specify overrides in localizations, Yext Search will use what is specified in either the synonyms or query suggestions objects for the primary language.
Here's an example where "en" is the primary locale and you want to set overrides for query suggestions in en_gb and es:
{
"autocomplete": {
"hardcodedPrompts": [
"Big Burger",
"Smoothie",
"Locations near me"
]
},
"localizations": {
"en_gb": {
"autocomplete": {
"hardcodedPrompts": [
"Locations near me",
"Low calorie menu options",
"What is the refund policy"
]
}
},
"es": {
"autocomplete": {
"hardcodedPrompts": [
"Locales cerca de mi",
"Opciones sin mucho calories",
"Algo otro"
]
}
}
}
}
In the above example, if the experience also had it and fr languages, users would see the top-level prompts in those languages (Big Burger, Smoothie, Locations near me).
We most often see people choosing Option 1 if they have both a US and a UK website where content is mostly the same except for CTA links they want to drive to the respective sites.
localizations vs. supportedLocales vs. countryRestrictions
These three properties operate very differently but are often confused:
-
localizationsprovides overrides for one or more locales for synonyms or query suggestions. If you are using separate configurations for each language, you don't need to include this. -
supportedLocalesdefines what profile languages should be indexed by your Search configuration. You will need to specify all language codes controlled by this configuration based on what's in your Knowledge Graph. If you are using separate configurations for each language, you don't need to include this. -
countryRestrictionsdefines what countries should be supported for the sake of limiting and optimizing location search (builtin.location). Specify country codes for all entities you want to be searchable by location. This is designed to optimize location searching and remove unnecessary noise. You can also add a Bounding Box to limit location searching to an even tighter area, which is best for any regional brands.
Multi-Language Frontend
Overview
The locale_config.json and global_config.json files help define the scope of your experience and how it connects to:
- The SDK Version specified in
global_config.json - The Search Configuration via the
experienceKey - Content via the
localefor identifying which content to surface on search results and which translations to pull in from the SDK
For a single-language experience, you need to update three things:
-
experienceKey(inlocale_config.json) -
locale(inlocale_config.json) - defaults to 'en' -
cloudRegion(inglobal_config.json) - defaults to 'us' -
cloudChoice(inglobal_config.json) - defaults to 'multi', which uses any of our consumer serving regions powered by AWS or GCP. Update to 'gcp' to limit queries to only GCP-based regions.
When building a multi-language experience, you can also set:
- Fallback behavior across languages to inherit page configuration or layout when not specified
- Translation file paths so the system knows where custom translations are located
-
URL Override if you want a certain locale's URL path to differ from the default pattern set in the
urlFormatobject - Params that are arbitrary strings you want to make available to HBS templates for a given locale (e.g., for a header or footer)
The locale_config.json File
The locale_config.json file has three main components:
-
defaultlocale - required; the template repo defaults to "en" -
localeConfig- where you add locale-specific configuration, like theexperienceKey -
urlFormat- determines the URL format of generated pages
Here's an example for a site in English, French, and German:
{
"default": "en",
"localeConfig": {
"en": {
"experienceKey": "brand_en"
},
"fr": {
"urlOverride": "france/{pageName}.{pageExt}",
"translationFile": "fr.po",
"experienceKey": "brand_fr"
},
"de": {
"fallback": ["fr"],
"translationFile": "de.po",
"experienceKey": "brand_de"
}
},
"urlFormat": {
"baseLocale": "{language}/{pageName}.{pageExt}",
"default": "{pageName}.{pageExt}"
}
}
For each language in your experience, include it in the localeConfig object. The only required sub-property is experienceKey. The fallback, translationFile, and urlOverride properties are optional and are for more advanced builds.
Note: Certain features are not supported in every language, so set a fallback for any locales outside of the six core languages listed in the Supported Languages reference doc.
URL Format
We recommend setting your URL format to:
"urlFormat": {
"baseLocale": "{language}/{pageName}.{pageExt}",
"default": "{pageName}.{pageExt}"
}
In urlFormat.default, you specify the URL path for the default locale's pages. For any other locale, urlFormat.baseLocale is used. These paths are all relative to the desktop directory.
If your domain is "search.brand.com", the object above would produce pages like:
-
search.brand.com/index.html(English universal) -
search.brand.com/fr/index.html(French universal) -
search.brand.com/locations.html(English locations) -
search.brand.com/fr/locations.html(French locations)
To break the pattern for a specific locale, specify a urlOverride in the locale config (as shown in the French example above). This would change the French URLs to:
search.brand.com/france/index.htmlsearch.brand.com/france/locations.html
Custom Params
In a more advanced build, include a params property within the locale object to specify arbitrary parameters. These values will be made available by Jambo to any HBS partial it compiles. Example:
"fr": {
"experienceKey": "french-experience",
"params": {
"CustomFrenchVar": "Ouais",
"SiteAttributes": {
"French": "Wine"
}
},
"urlOverride": "/vive/la/france/{pageName}.{pageExt}"
}
Using Live Preview
Live Preview works the same as in a single-language experience. To toggle between languages, modify the URL path to match what you specified in locale_config.json. For example, with the default URL settings, add "/languageCode" to the end of the preview URL.
Default URLs:
livepreview.sandboxlandingpagespreview.com/livepreview.sandboxlandingpagespreview.com/locations
Modified for the "es" locale:
livepreview.sandboxlandingpagespreview.com/eslivepreview.sandboxlandingpagespreview.com/es/locations
Building Pages and Cards for Multiple Languages
Creating Pages
When you create a new page in a single-language experience, you include only the [pageName], e.g., "locations", which generates:
pages/locations.html.hbsconfig/locations.json

Use this naming for your default language. For any additional languages, include the locale code: [pageName].[localeCode], e.g., "locations.fr", which generates:
pages/locations.fr.html.hbsconfig/locations.fr.json

The locale code must match the locale_config.json locale code / the profile locale code in the Knowledge Graph. The [pageName].[localeCode] notation tells Jambo which pages are associated to which locale, what the URL paths should be, and which pages share the same pageName parent for fallback behavior.
Here's what your file directory might look like with Universal Search, Locations, and FAQs for English (default), German, Italian, Spanish, and French:

Fallback Behavior
Fallback behavior lets you "fallback" to the default language (or another language if specified in locale_config.json) to reduce duplicative work. We always fallback to the default language, but you can optionally specify a different fallback language in locale_config.json.
If you are creating a Search experience using a language other than the 6 main supported languages, you must set a fallback language to one of the supported languages to avoid build errors.
For config.json files
For pages that share the same [pageName], we do a shallow merge of the configuration files. A shallow merge only goes one level deep - additional language pages can inherit top-level properties like verticalsToConfig or componentSettings but it's all or nothing. If you want different settings for the Facets object on your English and French page, you'll need to specify your full componentSettings object in the fr.json file, including components other than Facets.
For example, a minimal config.json for an additional language could look like:
{
"verticalKey": "locations",
"pageTitle": "Établissements Chercher"
}
This means componentSettings and verticalsToConfig objects will fallback on the default language's versions.
Note: You must include verticalKey in all config.json files at a minimum. All other top-level properties are optional and if not included will shallow merge with the default / fallback locale(s).
For html.hbs files
If you don't have an html.hbs file for a non-default language, Jambo uses the default language's html.hbs file for the layout. In many cases, you can delete the html.hbs file for additional languages when you want the verticals to look exactly the same across languages.
Keep in mind that all verticals must have a config.json file, but not all verticals need the layout/html.hbs file. If you don't have the config.json file, the vertical will not exist in that language.
Here's an example file directory using fallback for layout, where FAQs use the same layout for all languages, Universal Search is overridden in Spanish and Italian, and Locations is overridden in German:

Fallback Scenarios
Scenario 1: Site with 3 languages that are completely consistent across languages
For all 3 verticals in all languages, exactly the same in terms of components and verticalsToConfig except translated strings:
- Create pages using the proper notation
[pageName].[languageCode] - Delete the
pages/html.hbsfile for all pages except the default language - In the
config/jsonfile for each non-default language, only specifyverticalKeyandpageTitle(optionallymetaDescription,canonicalUrl, orkeywords) - Add any translations needed to your top-level translation file for the language

Example config/faqs.fr.json:

Scenario 2: Site with 3 languages that have same verticals but want to use different cards/components
When you want the verticals to look or behave differently across languages, do not rely on fallback behavior. Specify the full layout or config for each page explicitly - keep the pages/html.hbs files and keep the full componentSettings and/or verticalsToConfig objects in every config file.
Scenario 3: Site with 3 languages that have different verticals by language ("jagged site structure")
When data is not available for all verticals in all languages, create pages only for the vertical/language combinations you want to support. For example, if you want Universal Search and Locations in all 3 languages, Products in 2 languages (en, fr), and FAQs in only English, you would create 9 pages instead of 12.

Multi-Language Cards
The Theme includes multi-language versions of cards with translations for any strings baked into the card. Use these for any multi-language site as a best practice. They follow the naming convention multilang-[card description].
When you fork a card, fork a multi-language card if you plan to use it for multiple languages.
Managing Translations
Translation Files (.po files)
Translation files are .po (portable object) files. They contain instructions for translating default language strings (typically English) into the other languages your site supports.
The structure of a .po file:
msgid untranslated-string msgstr translated-string msgctxt context // optional
- msgid - the string in the default language
- msgstr - the string in the target language
-
msgctxt - optional context to help the translator; combined with
msgid, this constitutes a unique key
You will have an individual file for each alternate language your experience supports, for example es.po and fr.po. These live under the translations folder in your Jambo site.
Example - translating "Call" to Spanish:
msgid "Call" msgstr "Llama" msgctxt "To call an office, as a verb"
You may also encounter .pot (portable object template) files, which contain only the msgid without msgstr. These are templates that house the to-be-translated content.
Types of Translatable Content
Static Content
Content that does not depend on entity profile data - for example, vertical labels and placeholder text - is typically hardcoded in the default language in the config.json files. Because you create separate config.json files for each language, you just need to ensure the content for the target language is reflected in those files.
Answers Library Translated Content
Several areas where text appears - like the No Results text - are not specified in the pages or cards files. The Answers Library (as of version 1.6) has built-in translations for supported languages. If you are implementing Search in an unsupported language, or want to change these translations, you will need to override the components.
Dynamic Card Content
Card content from the Knowledge Graph needs to be translated in real-time as results are returned. Use the translateJS function in your card's component.js file to identify content to be translated.
Simple Example
showMoreText: {{ translateJS phrase='Show more' }}
To add a Spanish translation, in es.po:
msgid "Show more" msgstr "Ver más"
Example with Context
When the same word is used in different contexts:
ctaText: {{ translateJS phrase='Call now' context='Call is a verb' }}
In es.po:
msgid "Call" msgstr "Llama" msgctxt "Call is a verb"
Example with Templated Content
To dynamically inject content from the Knowledge Graph, indicate the content to be replaced within square brackets:
subtitle: {{ translateJS phrase='My name is [[name]]' name=profile.name }}
In es.po:
msgid "My name is [[name]]" msgstr "Mi nombre es [[name]]"
Example with Plural Form
For text that varies based on count:
stock: {{ translateJS phrase='One option' pluralForm='Many options' count=profile.count }}
In es.po (msgstr[0] = singular, msgstr[1] = plural):
msgid "One option" msgid_plural "Many options" msgstr[0] "Una opción" msgstr[1] "Muchas opciones"
template.hbs
For hardcoded text in your template.hbs file, use {{ translate phrase=""}}:
<button>{{ translate phrase='My button' }}</button>
<button>{{ translate phrase='My [[name]]' name={{someName}} }}</button>
Jambo Commands - Extract Translations
The Extract Translations Jambo Command analyzes your repository and extracts strings that require translations into a .pot file. Upload that .pot file into your translation software of choice, which should output a .po file. Then add that .po file (or copy its contents) into your translations/ directory.
Integration Considerations
The process for multi-language integration follows the same process as a single-language experience with a few key differences for each locale. These differences apply to both the search bar integration and the search results page.
The following steps assume your website follows a standard multi-language structure where each language has its own subfolder:
-
brand.com(primary English locale) -
brand.com/fr(French locale) -
brand.com/de(German locale)
Search Bar Integration
The search bar integration is essentially the same for each locale. Make sure to define the locale-specific variables locale and redirectUrl within the initAnswers function:
<head>
<link
rel="stylesheet"
type="text/css"
href="https://assets.sitescdn.net/answers-search-bar/v1.6/answers.css"
/>
<script src="https://assets.sitescdn.net/answers-search-bar/v1.6/answerstemplates.compiled.min.js"></script>
<script>
function initAnswers() {
ANSWERS.init({
apiKey: "REPLACE_ME_API_KEY",
experienceKey: "REPLACE_ME_EXPERIENCE_KEY",
experienceVersion: "PRODUCTION",
locale: "en", // e.g. en or fr
businessId: "REPLACE_ME_BUSINESS_ID",
templateBundle: TemplateBundle.default,
cloudRegion: "us",
cloudChoice: "multi",
onReady: function() {
ANSWERS.addComponent("SearchBar", {
container: ".search_form",
name: "search-bar",
redirectUrl: "REPLACE_ME_SEARCH_RESULT_URL",
placeholderText: "Search...",
});
},
});
}
</script>
<script
src="https://assets.sitescdn.net/answers-search-bar/v1.6/answers.min.js"
onload="ANSWERS.domReady(initAnswers)"
async
defer
></script>
</head>
The locale is the desired locale of the search bar (e.g., en or fr) and the redirectUrl is the Search Results page URL for that locale.
Hosting Data in the EU Cloud Region
By default, your search experience and data is stored in the US cloud region. To use the EU region:
- Change
cloudRegionto"eu" - Optionally set
cloudChoiceto"gcp"to direct analytics events to a GCP-only events URL - Replace all references to
https://assets.sitescdn.netwithhttps://assets.eu.sitescdn.net
JS Snippet Results Page Integration
Stand up a results page for each locale:
brand.com/searchbrand.com/fr/searchbrand.com/de/search
Place the standard JS Snippet into each page. The only difference per locale is a data-path within the answers-container div that points to the correct page in your Jambo repo. For example, the Japanese locale on yext.com:
<div id="answers-container" data-path="ja/index.html"></div> <script src="https://search.yext.com/iframe.js"></script>

Each search results page for each locale must have data-path defined.
Subdomain Results Page Integration
There are no differences in the Subdomain results page integration. Once the CNAME is properly set up and configured to the pagescdn.com bridge, you can access your multi-language sites immediately.
For a subdomain configured at https://www.search.yext.com/, the primary English locale loads by default. To access a different locale, add the locale path: https://search.yext.com/ja/index.html. Set this as the redirectUrl for that locale's search bar.
Multi-Language Overlay Module Integration
To add the overlay to an international site, include the experiencePath attribute in the overlay module integration snippet. If the French page is "fr/index.html":
<script>
function initAnswersOverlay() {
YextAnswersOverlay.init({
experiencePath: "fr/index.html",
//rest of overlay config as normal
});
}
</script>
Best Practices
General Best Practices
- Don't let collecting content stress you out. Start with limited verticals or features and gradually build out over time based on customer behavior. Users in different languages may search for or want to see different information anyway.
- Remember that language profiles must be consistent for your entities so all entities have the same "variation" of a language. Each language experience is strictly limited to a locale.
- Build one language out first, then add additional languages once you've established the look and feel and determined what content to include. It's much easier to add languages after you have one that meets your needs.
Search Configuration Best Practices
- In most cases, create a separate single-language Search Configuration for each language (Option 2). This allows the most flexibility and least complexity when making updates.
- Make sure you understand the difference between
supportedLocales,countryRestrictions, andlocalizations. If you're using one configuration for multiple languages that map to different language codes in the Knowledge Graph, you must at least includesupportedLocales. If you want any overrides, uselocalizations. If you usebuiltin.locationin your searchable fields and your entities are in multiple countries, includecountryRestrictions.
Frontend Best Practices
- Add one language first and confirm with your team or client that it looks good before adding more languages.
- For verticals like FAQs that will look the same across all languages, take advantage of Fallback: delete the non-default
html.hbsfiles and limit what you provide in theconfig.jsonfile. - If cards are meant to look the same except for some hardcoded strings, use translation files instead of creating separate forked cards for each language.