在 vue (nuxt) 中动态更改 facebook sdk lang 代码

change facebook sdk lang code dynamically in vue (nuxt)

我目前正在 nuxt 中进行类似的简单实现。当我使用 1i8n 更改语言时,我想相应地更改 facebook sdk 语言,因此当我更改整个应用程序语言时,按钮会以给定的语言代码呈现。我的代码如下所示:

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'));
    }
}

它有效,但没有发生动态变化,我是否错过了按钮 sdk 上的异步之类的东西???不知道,我是 vue 的新手,非常感谢帮助。

我用this.$router.go(0);点击语言切换的按钮解决了,我希望用另一种方式,但仍然找不到,反正现在页面重新加载时语言会改变以及 sdk 的 lang 代码,如果其他使用适当的语言。也许有一天我会找到更优雅的解决方案

That won’t work, the SDK can only be embedded and initialized once.

这不完全正确:有一个解决方法。

如果在头部添加新的脚本,加载一次就会执行。对于任何脚本都是如此。如果没有,则意味着该脚本有一个保护措施,可以通过检查其变量之一是否已定义来再次阻止 运行 相同的代码。

对于 Facebook SDK,它将检查 FB 是否已在全局定义,因此您只需在添加具有不同语言环境的新 sdk 脚本之前将其删除。

我的代码看起来有点不同,但我也在使用 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>

您应该注意的事项:

  • 语言环境是我元素的 key 属性的一部分,以使其在语言环境更改时重新呈现,以删除 sdk 添加的内容(属性、子元素)
  • 有一个观察者在区域设置更改时调用 resetFacebookSdk
  • 我修改了 sdk 代码片段以删除脚本标签(如果它已经存在)而不是什么都不做。这样我们就可以重新创建了。
  • 元素 .fb-customerchat 已使用 key 属性清除,但 sdk 已使用新元素 #fb-root 对其进行包装。方法 resetFacebookSdk 负责将 .fb-customerchat 移出包装器并将其删除。

您可以在 our website 上看到它的实际效果(您可以在页脚中切换语言)。

希望对您有所帮助。如果有什么不清楚的地方,请告诉我。