Multilingual Support

Ekoo supports multilingual audio content, allowing you to serve audio in the right language based on your visitor's locale.

How It Works

When you set the data-ekoo-locale attribute on a widget, Ekoo filters audio content to show only tracks tagged with that locale. The attribute has three behaviours: omitted or empty, every published audio is served; set to auto, the browser's language is used; set to a tag Ekoo does not know, no audio is served.

Locale Attribute

Set the locale directly on the widget element:

French locale
html
1<script src="https://app.ekoo.co/widgets/widget-4.0.0-standalone.js"</script>
2
3<ekoo-widget
4 data-ekoo="YOUR_WEBSITE_ID"
5 data-ekoo-product-id="YOUR_PRODUCT_ID"
6 data-ekoo-locale="fr"
7></ekoo-widget>
English locale
html
1<ekoo-widget
2 data-ekoo="YOUR_WEBSITE_ID"
3 data-ekoo-product-id="YOUR_PRODUCT_ID"
4 data-ekoo-locale="en"
5></ekoo-widget>

Supported Locale Values

⚠️

Ekoo uses its own locale codes

Ekoo locale codes may differ from standard ISO/BCP47 codes. For example: Chinese Simplified is cn (not zh-Hans), Japanese is jp (not ja), Korean is kr (not ko). See the Locale Mapping section below if your site uses standard codes.

ValueLanguage
frFrench
enEnglish
esSpanish
deGerman
daDanish
svSwedish
fiFinnish
noNorwegian
itItalian
nlDutch
ptPortuguese
arArabic
ukUK
bgBG
ruRussian
plPolish
trTurkish
zh-HansChinese (Simplified)
zh-HantChinese (Traditional)
yueChinese (Hong Kong)
jaJapanese
koKorean

Auto Detection

With data-ekoo-locale="auto", the widget sends the browser's full navigator.language tag, such as zh-Hant-HK, and Ekoo resolves it one subtag at a time. A tag Ekoo cannot resolve serves no audio rather than audio in another language. Omitting the attribute does not enable detection: it disables filtering.

Automatic language detection
html
1<ekoo-widget
2 data-ekoo="YOUR_WEBSITE_ID"
3 data-ekoo-product-id="YOUR_PRODUCT_ID"
4 data-ekoo-locale="auto"
5></ekoo-widget>

No filtering (all languages)

By omitting the data-ekoo-locale attribute, all published audios for the product will be accessible regardless of locale:

No locale filtering
html
1<ekoo-widget
2 data-ekoo="YOUR_WEBSITE_ID"
3 data-ekoo-product-id="YOUR_PRODUCT_ID"
4></ekoo-widget>

JavaScript Configuration

The locale can also be set via window.ekooOptions. The locale goes inside the widgets array (not as a top-level property):

Locale via ekooOptions
javascript
1// window.ekooOptions sets the locale for programmatic widget creation
2window.ekooOptions = {
3 websiteId: "YOUR_WEBSITE_ID",
4 widgets: [
5 {
6 nodeId: "my-container",
7 productId: "my-product",
8 locale: "fr"
9 }
10 ]
11};

Setting Locale Dynamically

You can change the locale at runtime by updating the attribute and reloading the widget:

Dynamic locale change
javascript
1const widget = document.querySelector('[data-ekoo]');
2widget.setAttribute('data-ekoo-locale', getUserLocale());
3window.ekooReload();

React Example

In a React application, you can pass the locale as a prop and trigger a reload when it changes:

React locale integration
tsx
1import { useEffect } from 'react';
2
3interface EkooWidgetProps {
4 websiteId: string;
5 productId: string;
6 locale?: string;
7}
8
9export function EkooWidget({ websiteId, productId, locale }: EkooWidgetProps) {
10 useEffect(() => {
11 window.ekooReload();
12 }, [locale]);
13
14 return (
15 <ekoo-widget
16 data-ekoo={websiteId}
17 data-ekoo-product-id={productId}
18 data-ekoo-locale={locale}
19 ></ekoo-widget>
20 );
21}

Locale Mapping

If your site uses standard BCP47 or ISO language codes (e.g., zh-Hans, ja, ko), you may need a mapping script to convert them to Ekoo locale codes. Add this script before the Ekoo widget script:

Locale mapping script
html
1<script>
2// Locale mapping: your site's language tag → Ekoo code
3// Add this BEFORE the Ekoo widget script
4(function() {
5 var lookup = {
6 'fr': 'fr',
7 'fr': 'fr',
8 'en': 'en',
9 'en': 'en',
10 'es': 'es',
11 'es': 'es',
12 'de': 'de',
13 'de': 'de',
14 'da': 'da',
15 'da': 'da',
16 'dk': 'da',
17 'sv': 'sv',
18 'sv': 'sv',
19 'fi': 'fi',
20 'fi': 'fi',
21 'no': 'no',
22 'no': 'no',
23 'nb': 'no',
24 'nn': 'no',
25 'it': 'it',
26 'it': 'it',
27 'nl': 'nl',
28 'nl': 'nl',
29 'vl': 'nl',
30 'pt': 'pt',
31 'pt': 'pt',
32 'ar': 'ar',
33 'ar': 'ar',
34 'uk': 'uk',
35 'uk': 'uk',
36 'bg': 'bg',
37 'bg': 'bg',
38 'ru': 'ru',
39 'ru': 'ru',
40 'pl': 'pl',
41 'pl': 'pl',
42 'tr': 'tr',
43 'tr': 'tr',
44 'cn': 'zh-Hans',
45 'zh-hans': 'zh-Hans',
46 'cn': 'zh-Hans',
47 'zh': 'zh-Hans',
48 'zh-cn': 'zh-Hans',
49 'tw': 'zh-Hant',
50 'zh-hant': 'zh-Hant',
51 'tw': 'zh-Hant',
52 'zh-tw': 'zh-Hant',
53 'zh-hk': 'zh-Hant',
54 'zh-mo': 'zh-Hant',
55 'hk': 'yue',
56 'yue': 'yue',
57 'hk': 'yue',
58 'yue-hk': 'yue',
59 'jp': 'ja',
60 'ja': 'ja',
61 'jp': 'ja',
62 'kr': 'ko',
63 'ko': 'ko',
64 'kr': 'ko'
65 };
66
67 window.ekooGetLocale = function() {
68 var lang = (document.documentElement.getAttribute('lang') || '').trim().toLowerCase();
69
70 // No lang attribute: no locale filter, the widget serves every audio.
71 if (!lang) return '';
72
73 // Drop one subtag at a time from the right, so zh-Hant-HK is tried before
74 // zh-Hant and zh, and the script subtag is never skipped over.
75 var subtags = lang.split(/[-_]/);
76 for (var n = subtags.length; n >= 1; n--) {
77 var candidate = subtags.slice(0, n).join('-');
78 if (lookup[candidate]) return lookup[candidate];
79 }
80
81 // Unknown language: pass the tag through unchanged. The server answers with
82 // an empty catalogue, which is the honest result. Never substitute another
83 // language here.
84 return lang;
85 };
86})();
87</script>

Then use the helper function to set the locale dynamically:

Using the mapping
html
1<div
2 data-ekoo="YOUR_WEBSITE_ID"
3 data-ekoo-product-id="YOUR_PRODUCT_ID"
4></div>
5
6<script>
7 // After DOM is ready, set the locale from the mapping
8 var widget = document.querySelector('[data-ekoo]');
9 if (widget && window.ekooGetLocale) {
10 widget.setAttribute('data-ekoo-locale', window.ekooGetLocale());
11 }
12</script>
💡

Tag your audio content

Make sure your audio content in the backoffice is tagged with the correct locale. If you forget to tag audio, it won't appear when a locale filter is active.
ℹ️

UI language is not affected

The locale attribute only filters which audio is displayed — it does not translate the widget's UI elements.