更改来自 API 的语言相关内容的最佳实践

best practice to change language dependent content coming from APIs

  1. 背景:
    我有一个 SPA (Vuejs),我在前端和后端都实现了本地化。更改语言时无需重新加载页面即可成功更新内容。
  2. 问题:
    但有些内容(如所选语言的产品描述)来自 API,当我更改语言时它不会自动更新。如果我刷新页面或再次调用 API,它会起作用。
  3. 问题:
    在不刷新页面并手动调用所有 APIs 的情况下更改来自 APIs 的语言相关内容的最佳做法是什么。

    谢谢!

我相信有很多方法可以做你想做的事。 例如。我们有模型有一些字段可以本地化,但是我们只支持三种语言,而且字段比较短。

在那种情况下,我们只需要后端 api return 字符串的所有本地化版本,例如:

GET /products 可以 return:

[{
  sku: '1',
  name: {
    en: 'Product name',
    nl: 'Productnaam',
    fr: 'Nom du produit'
  }
}]

然后我们根据路由参数在 VueJs 中显示... {{product.name[$route.params.locale] || product.name[en]}}(我们有一个可组合的方法来代替,但你明白了。

但是,对于某些端点,您可能并不总是希望 return 服务器的所有本地化版本,只是因为它太大了(例如,您 post 的博客post使用多种语言,而您支持 5 种语言可能只会生成您不想生成的负载...)

在这种情况下,您只需在 vuejs 中观察语言环境的变化,并获取本地化版本。

我自己不喜欢的第三个选项是“语言切换”,基本上是重新加载整个页面...

无论哪种方式 - 有很多方法可以满足您的需求,这完全取决于您的用例和您的个人喜好。

我设法做到了,我不知道这是否是最佳实践,但它是一个可行的解决方案并且对其他人有用:

App.vue:

  • 我有一个 LocaleChanger 组件,它在每次语言更改时发出 localChanged
  • 视图已加载到 router-view 中,因此我将 rerenderKey 添加到其键中。并且当它被更改时,所有内容都将在当前视图中重新呈现(包括相应组件的API)。
  • 并且由于我所有的 API 都在其中调用,因此它们将被再次调用。
    <template>
        <LocaleChanger @localChanged="forceRerender"/>
        <div id="nav"> 
            <router-link :to="{ name: 'Home', params: {'lang':$i18n.locale}}">{{$t('pages.home')}}</router-link> |
        </div>
        <router-view :key="rerenderKey"></router-view>
    </template>

    <script>
        data () {
            return {
                rerenderKey: 0
            };
        },
        methods: {
            async forceRerender(){
                await this.$router.push({name: this.$route.name, params: { ...this.$route.params, lang: this.$i18n.locale }})
                this.rerenderKey += 1;
            },
        }
    </script>

并且由于我的 API-s 需要 Accept-language header,我将其添加到 main.js 到 axios.interceptors.request

    axios.interceptors.request.use(
        function (config) {
            config.headers['Accept-Language'] = store.state.locale;
            return config;
        },
        function (error) {
            return Promise.reject(error);
        }
    );

当使用 vue-i18n 插件时,您可以发送 exampleText 之类的变量,而不是从后端发送本地化文本,并使用 {{$t(yourLangVar)}} 和 [= 在您的 vue 代码中翻译它们12=]