i am currently working on a simple like implementation in nuxt. when i change the language with 1i8n, i want to change the facebook sdk language accordingly, so the button renders in the given language code when i change the overall app language. my code looks like this:
import config from '@/config'
export default {
data() {
return {
FB_APP_ID: config.appname.FB_APP_ID
}
},
mounted() {
var langua;
if (this.$i18n.locale == 'en') {
langua = "en_US";
}
if (this.$i18n.locale == 'de') {
langua = "de_DE";
}
window.fbAsyncInit = () => {
FB.init({
appId: this.FB_APP_ID,
cookie: true,
xfbml: true,
version: 'v2.8'
})
}
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/" + langua + "/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
}
it works but the dynamic change is not happening, do i miss something like async on the button sdk here ??? no idea, i am new to vue, help is appreciated thanks a lot.
That won’t work, the SDK can only be embedded and initialized once.
This is not entirely true: there is a workaround.
If you add a new script to the head, it will be executed once loaded. This is true for any script. If it doesn't, it means the script has a guard that prevents running the same code again most likely by checking if one of its variables is already defined.
In the case of Facebook SDK, it will check if FB
is already defined globally so you simply need to delete it before adding your new sdk script with a different locale.
My code looks a bit different, but I'm also using Nuxt:
<template>
<div
:key="`fb-chat-${$i18n.locale}`"
class="fb-customerchat"
:page_id="pageId"
theme_color="#4586ff"
greeting_dialog_display="hide"
:logged_in_greeting="$t('greeting')"
:logged_out_greeting="$t('greeting')"
></div>
</template>
<script>
export default {
name: 'FacebookChat',
data() {
return {
pageId: process.env.FACEBOOK_PAGE_ID,
}
},
watch: {
'$i18n.locale': 'resetFacebookSdk',
},
mounted() {
this.initFacebookSdk()
},
methods: {
initFacebookSdk() {
if (!process.browser) return
const locale = this.$i18n.locale === 'de' ? 'de_DE' : 'en_US'
delete window.FB // needs to be undefined when inserting a second script with different locale
window.fbAsyncInit = function () {
window.FB.init({
appId: process.env.FACEBOOK_APP_ID,
autoLogAppEvents: true,
xfbml: true,
version: 'v10.0',
})
}
;(function (d, s, id) {
let js = d.getElementById(id),
fjs = d.getElementsByTagName(s)[0]
if (js) js.parentNode.removeChild(js) // remove script tag if exists
js = d.createElement(s)
js.id = id
js.src = `https://connect.facebook.net/${locale}/sdk/xfbml.customerchat.js`
fjs.parentNode.insertBefore(js, fjs)
})(document, 'script', `facebook-jssdk-${this.$i18n.locale}`)
},
resetFacebookSdk() {
const fbRoot = this.$el.closest('#fb-root')
if (!fbRoot) return
// Move fb-customerchat element outside of fb-root (created by Facebook SDK)
fbRoot.parentNode.insertBefore(this.$el, fbRoot)
// Delete fb-root to let Facebook SDK create it again
fbRoot.parentNode.removeChild(fbRoot)
this.initFacebookSdk()
},
},
}
</script>
What you should pay attention to:
key
attribute of my element to make it re-render on locale change in order to remove what the sdk has added (attributes, child elements)resetFacebookSdk
on locale change.fb-customerchat
is cleaned up with the key
attribute, but the sdk has wrapped it with a new element #fb-root
. The method resetFacebookSdk
is taking care of moving .fb-customerchat
outside of that wrapper and deleting it.You can see it in action on our website (you can switch language in the footer).
Hope it helps. Let me know if something is not clear.