更改来自 API 的语言相关内容的最佳实践
best practice to change language dependent content coming from APIs
- 背景:
我有一个 SPA (Vuejs),我在前端和后端都实现了本地化。更改语言时无需重新加载页面即可成功更新内容。
- 问题:
但有些内容(如所选语言的产品描述)来自 API,当我更改语言时它不会自动更新。如果我刷新页面或再次调用 API,它会起作用。
- 问题:
在不刷新页面并手动调用所有 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=]
- 背景:
我有一个 SPA (Vuejs),我在前端和后端都实现了本地化。更改语言时无需重新加载页面即可成功更新内容。 - 问题:
但有些内容(如所选语言的产品描述)来自 API,当我更改语言时它不会自动更新。如果我刷新页面或再次调用 API,它会起作用。 - 问题:
在不刷新页面并手动调用所有 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=]