Modularized approach and remember language preference.
Create a SSI php include file and drop this in it:
<!-- Wappler include head-page="" appconnect="local" is="dmx-app" components="{dmxDatastore:{}}" -->
<script src="../../dmxAppConnect/dmxBrowser/dmxBrowser.js"></script>
<script src="../../dmxAppConnect/dmxDatastore/dmxDatastore.js" defer=""></script>
<script src="../../dmxAppConnect/dmxFormatter/dmxFormatter.js" defer=""></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/19.4.4/i18next.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/i18next/i18next-http-backend@1.0.8/i18nextHttpBackend.min.js"></script>
<script>
var translationLoaded = false
var callback = function(){
i18next
.use(window.i18nextHttpBackend)
.init({
//Our website will only support english and spanish for the time being
whitelist: ['en', 'es'],
// Look for language setting in local storage. If not found use browser language.
lng: dmx.parse("i18n.data[0].language") ? dmx.parse("i18n.data[0].language") : dmx.parse('browser.language.substr(0, 2)'),
// If browser is not in english or spanish it will show english
fallbackLng: 'en',
// We load our strings from here. It will take the name of the page as the name of the file.
backend: { loadPath: '../../assets/translations/{{lng}}/'+dmx.app.name+'.json'}
})
.then(updateDOM)
}
if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
callback();}
else {
document.addEventListener("DOMContentLoaded", callback);}
//We added a condition to make sure the translation function is not called before the translation is available. Avoids some console warnings.
dmx.Formatter('string', 't', function (key, options) {
if (translationLoaded)
return i18next.t(key, options);
else
return key
})
//Reevaluates all the App Connect bindings and updates contents of the page based on language
function updateDOM() {
dmx.requestUpdate()
dmx.global.set('translationLoaded', true)
dmx.global.set('translationLanguage', i18next.language)
dmx.parse("i18n.upsert({$id: 1, language: translationLanguage},{language: translationLanguage})")
translationLoaded = true
}
</script>
<div is="dmx-browser" id="browser"></div>
<dmx-datastore id="i18n"></dmx-datastore>
Remember to change loadPath
value if you want to load json translation files from a different place.
The code above will take the files from /assets/translations/{{lng}}/{{pagename}}.json
So if your page is named dashboard
and french
is selected and supported(not in our example) it it will attempt to download /assets/translations/fr/dashboard.json
Once you have this SSI PHP include file configured as per your needs you just need to call it from each single page you want to translate by adding <?php include '../includes/i18n.php'; ?>
to the body.

Remember that the language chosen will be the one stored in local storage or browser language the first time you load the page.
If you want the user to be able to select the language and the browser to remember the selection just run i18next.changeLanguage('es').then(updateDOM)
I am currently using a footer and a dropdown for this.
<div class="dropdown-menu dropdown-menu-sm dropdown-menu-right">
<a dmx-bind:href="browser.location.pathname+'#'" class="dropdown-item" onclick="i18next.changeLanguage('en').then(updateDOM)"><img alt="English" src="../../assets/img/icons/flags/en.svg" class="mr-2">English</a>
<a dmx-bind:href="browser.location.pathname+'#'" class="dropdown-item" onclick="i18next.changeLanguage('es').then(updateDOM)" data-toggle="none"> <img alt="Spanish" src="../../assets/img/icons/flags/es.svg" class="mr-2">Spanish</a>
</div>
This will change the language to one of them and call the updateDOM function that will reevaluate all AC bindings, update the DOM and store the selected language in the data store component so it’s remembered next time the user visits the website.
If you have a user database and you want to store their preferred language in the database you could easily sync the datastore language setting with the database user preferred language each time the user logs in or changes the setting in his account/profile settings. But this is not covered in this example.
This new example was to modularize our i18nextr integration and store language selection in local browser storage so it’s remembered.
Remember that there will still be a flickering if you do not hide body until translations are available.
<body class="application application-offset" is="dmx-app" id="dashboard" dmx-show="translationLoaded">
Note: If you use this approach remember you don’t have to call these 3 App Connect libraries in the pages you add this SSI PHP include file as they are already called by the SSI.
<script src="../../dmxAppConnect/dmxBrowser/dmxBrowser.js"></script>
<script src="../../dmxAppConnect/dmxDatastore/dmxDatastore.js" defer=""></script>
<script src="../../dmxAppConnect/dmxFormatter/dmxFormatter.js" defer=""></script>