vue 在从后端加载 i18n 翻译后显示页面
vue show page after i18n translations loaded from backend
在我的应用程序中,管理员可以编辑翻译,因此我需要从我的后端预加载它们并在我拥有的 vue 应用程序中进行初始化。所以我发现 vue i18n 包有延迟加载消息的能力 (link) 。但是在他们的示例中,他们已经使用默认 (en) 消息初始化了 vue,但就我而言,我没有预加载默认消息。所以我想在创建 VueI18n 的新实例时从后端加载消息。
这是 i18n.js
文件:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import {syncGetData} from "@/apiUtil";
import NProgress from 'nprogress'
import './sass/nprogress.scss'
Vue.use(VueI18n)
let loadedLanguages = []
export const i18n = new VueI18n({
locale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE,
fallbackLocale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE,
messages: loadLanguage(navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE)
})
function setI18nLanguage (lang) {
i18n.locale = lang
document.querySelector('html').setAttribute('lang', lang)
return lang
}
export function loadLanguage(lang) {
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
NProgress.start();
return syncGetData('/api/translations/' + lang)
.then(function(data) {
setI18nLanguage(lang)
loadedLanguages.push(lang)
return data;
})
.catch(function (error) {
console.error(error)
}).finally(function () {
NProgress.done();
});
}
这里还有 main.js
(简体):
import Vue from 'vue'
import App from './App.vue'
import {i18n} from './i18n'
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
翻译的加载工作正常,但 Vue 在加载模板之前渲染模板,我看到的不是实际翻译,而是翻译键。我尝试使用 v-cloak
但没有用。
所以我想要实现的是,当翻译加载用户应该只看到加载栏(我正在使用 NProgress
,你可以在 i18n.js
中看到用法)并呈现仅在翻译加载后应用程序(可能不渲染但初始化)。我得到的是:加载栏和呈现的应用程序都没有实际翻译
提前致谢!
Michal Levý asnwer 之后的更新
现在,i18n.js
看起来像这样:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { syncGetData} from "@/apiUtil";
import NProgress from 'nprogress'
import './sass/nprogress.scss'
Vue.use(VueI18n)
let loadedLanguages = [];
export function initI18n() {
const lang = navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE
return syncGetData('/api/translations/' + lang)
.then(function(data) {
console.log(data)
setI18nLanguage(lang)
loadedLanguages.push(lang)
return new VueI18n({
locale: lang,
fallbackLocale: lang,
messages: data
})
})
.catch(function (error) {
console.error(error)
});
}
function setI18nLanguage (lang) {
document.querySelector('html').setAttribute('lang', lang)
return lang
}
export function loadLanguage(lang) {
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
NProgress.start();
return syncGetData('/api/translations/' + lang)
.then(function(data) {
setI18nLanguage(lang)
loadedLanguages.push(lang)
return data;
})
.catch(function (error) {
console.error(error)
}).finally(function () {
NProgress.done();
});
}
和main.js
是:
import Vue from 'vue'
import App from './App.vue'
import {initI18n} from './i18n'
import NProgress from "nprogress";
import './sass/nprogress.scss'
NProgress.start();
initI18n().then(function(i18n) {
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
}).finally(function () {
NProgress.done();
});
我可以确认现在消息已在 Vue 初始化之前加载,我的 App.vue
中的 b-z 我在 mounted
方法中有一个 console.log
:
mounted() {
console.log(this.$i18n.messages)
}
并且控制台日志的输出是 Object { main_title: "Calculation", tab_you: "You", tab_friend: "Your Friend",...}
,之前它是空对象。
但仍然 <h2 class="title-form">{{ $t('main_title') }}</h2>
呈现 main_title
而不是 Calculation
用这样的东西替换 VueI18n
初始化:
export function initI18n() {
const lang = navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE
return loadLanguage(lang).then(function(data) {
return new VueI18n({
locale: lang,
fallbackLocale: lang,
messages: data
})
})
}
main.js
import Vue from 'vue'
import App from './App.vue'
import { initI18n } from './i18n'
initI18n().then(function(i18n) {
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
})
Q更新后编辑:
看来你的本地化format是错误的。 VueI18 能够同时使用多种语言,所以你所有的翻译键都应该包含在“语言对象”
而不是:
{
main_title: "Calculation",
tab_you: "You",
tab_friend: "Your Friend",
...
}
你的API应该return
{
"en": {
main_title: "Calculation",
tab_you: "You",
tab_friend: "Your Friend",
...
}
}
...其中“en”是语言标识符
检查你的浏览器控制台,我相信 VueI18n 应该警告丢失的键...
在我的应用程序中,管理员可以编辑翻译,因此我需要从我的后端预加载它们并在我拥有的 vue 应用程序中进行初始化。所以我发现 vue i18n 包有延迟加载消息的能力 (link) 。但是在他们的示例中,他们已经使用默认 (en) 消息初始化了 vue,但就我而言,我没有预加载默认消息。所以我想在创建 VueI18n 的新实例时从后端加载消息。
这是 i18n.js
文件:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import {syncGetData} from "@/apiUtil";
import NProgress from 'nprogress'
import './sass/nprogress.scss'
Vue.use(VueI18n)
let loadedLanguages = []
export const i18n = new VueI18n({
locale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE,
fallbackLocale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE,
messages: loadLanguage(navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE)
})
function setI18nLanguage (lang) {
i18n.locale = lang
document.querySelector('html').setAttribute('lang', lang)
return lang
}
export function loadLanguage(lang) {
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
NProgress.start();
return syncGetData('/api/translations/' + lang)
.then(function(data) {
setI18nLanguage(lang)
loadedLanguages.push(lang)
return data;
})
.catch(function (error) {
console.error(error)
}).finally(function () {
NProgress.done();
});
}
这里还有 main.js
(简体):
import Vue from 'vue'
import App from './App.vue'
import {i18n} from './i18n'
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
翻译的加载工作正常,但 Vue 在加载模板之前渲染模板,我看到的不是实际翻译,而是翻译键。我尝试使用 v-cloak
但没有用。
所以我想要实现的是,当翻译加载用户应该只看到加载栏(我正在使用 NProgress
,你可以在 i18n.js
中看到用法)并呈现仅在翻译加载后应用程序(可能不渲染但初始化)。我得到的是:加载栏和呈现的应用程序都没有实际翻译
提前致谢!
Michal Levý asnwer 之后的更新
现在,i18n.js
看起来像这样:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { syncGetData} from "@/apiUtil";
import NProgress from 'nprogress'
import './sass/nprogress.scss'
Vue.use(VueI18n)
let loadedLanguages = [];
export function initI18n() {
const lang = navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE
return syncGetData('/api/translations/' + lang)
.then(function(data) {
console.log(data)
setI18nLanguage(lang)
loadedLanguages.push(lang)
return new VueI18n({
locale: lang,
fallbackLocale: lang,
messages: data
})
})
.catch(function (error) {
console.error(error)
});
}
function setI18nLanguage (lang) {
document.querySelector('html').setAttribute('lang', lang)
return lang
}
export function loadLanguage(lang) {
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
NProgress.start();
return syncGetData('/api/translations/' + lang)
.then(function(data) {
setI18nLanguage(lang)
loadedLanguages.push(lang)
return data;
})
.catch(function (error) {
console.error(error)
}).finally(function () {
NProgress.done();
});
}
和main.js
是:
import Vue from 'vue'
import App from './App.vue'
import {initI18n} from './i18n'
import NProgress from "nprogress";
import './sass/nprogress.scss'
NProgress.start();
initI18n().then(function(i18n) {
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
}).finally(function () {
NProgress.done();
});
我可以确认现在消息已在 Vue 初始化之前加载,我的 App.vue
中的 b-z 我在 mounted
方法中有一个 console.log
:
mounted() {
console.log(this.$i18n.messages)
}
并且控制台日志的输出是 Object { main_title: "Calculation", tab_you: "You", tab_friend: "Your Friend",...}
,之前它是空对象。
但仍然 <h2 class="title-form">{{ $t('main_title') }}</h2>
呈现 main_title
而不是 Calculation
用这样的东西替换 VueI18n
初始化:
export function initI18n() {
const lang = navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE
return loadLanguage(lang).then(function(data) {
return new VueI18n({
locale: lang,
fallbackLocale: lang,
messages: data
})
})
}
main.js
import Vue from 'vue'
import App from './App.vue'
import { initI18n } from './i18n'
initI18n().then(function(i18n) {
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
})
Q更新后编辑:
看来你的本地化format是错误的。 VueI18 能够同时使用多种语言,所以你所有的翻译键都应该包含在“语言对象”
而不是:
{
main_title: "Calculation",
tab_you: "You",
tab_friend: "Your Friend",
...
}
你的API应该return
{
"en": {
main_title: "Calculation",
tab_you: "You",
tab_friend: "Your Friend",
...
}
}
...其中“en”是语言标识符
检查你的浏览器控制台,我相信 VueI18n 应该警告丢失的键...