这里一共讲述两种方式 亲测过的
方式1:路由不会有 /en /zh 变化,而且刷新的时候还有些小问题 需要对layouts 公共布局文件进行处理, 这样处理会有一小会的白屏问题;
方式2:可以跟方式1一样 路由不会变化 也不会因刷新白屏 闪烁等问题; 也可以根据切换语言 改变路由 /en/about /zh/about , 问题 需要COPy出来一套代码放入_lang文件夹里面,如下图所示:
![]()
这种情况就是只有index 、local 页面可以进行语言切换 其他则不行;
方式1:
1.安装vue-i18n
npm install vue-i18@7 --save
【注意版本问题】:最开始我安装的 最新版本的 vue-i18 就报了很多错误; 卸载重新安装 7的版本就OK了;
以下是我的版本:"vue": "^2.6.14","element-ui": "^2.15.6", "vue-i18n": "^7.8.1",
2.新建locales文件,en-us.js / es-es.js / zh-cn.js ,分别对应 英文 / 西班牙 / 中文
![]()
export default {
login: {
title: "Sign In",
},
}
export default {
login: {
title: "Regístrate",
},
}
export default {
login: {
title: "注册",
},
}
3.新建untils文件夹,i18n-setup.js,语言转换
![]()
import Vue from "vue"
import VueI18n from 'vue-i18n';
import ElementLocale from 'element-ui/lib/locale'
Vue.use(VueI18n);
const i18n = new VueI18n();
const loadedLanguages = [] // 我们的预装默认语言
const locales = ["en-us", "es-es", "zh-cn"];//所有语言
const eleLocales = {
"en-us": "en",
"es-es": "es",
"zh-cn": "zh-CN"
}//对应elementUI多语言
const loadLanguageAsync = (lang) => {
// 如果语言相同
if (i18n.locale === lang) {
return Promise.resolve(lang)
}
// 如果语言已经加载
if (loadedLanguages.includes(lang)) {
i18n.locale = lang
return Promise.resolve(lang)
}
// 如果尚未加载语言
return Promise.all([import(/* webpackChunkName: "lang-[request]" */ `@/locales/${lang}.js`),
import(`element-ui/lib/locale/lang/${eleLocales[lang]}`)]).then(
([messages, eleMsg]) => {
i18n.setLocaleMessage(lang, {
...messages.default,
...eleMsg.default
})
ElementLocale.i18n((key, value) => i18n.t(key, value))
i18n.locale = lang
loadedLanguages.push(lang)
return lang
}
)
}
export {
locales,
i18n,
loadLanguageAsync
};
4.新建plugins文件夹,i18n.js,初始化语言
![]()
import { locales, i18n, loadLanguageAsync } from "@/untils/i18n-setup"
export default async ({ app, store, params, req }) => {
let lange = null;
if (process.browser) {//是客户端环境
lange = store.state.locale || navigator.language
} else {
lange = store.state.locale ||
(req && req.headers && req.headers['accept-language'] && req.headers['accept-language'].split(',')[0]);
}
// 初始化语言
if (locales.indexOf(lange) === -1) {
lange = "en-us";
}
await loadLanguageAsync(lange).then(() => {
app.i18n = i18n;
})
}
5.在nuxt.config.js添加引入
![]()
6.index页面
<div class="container">
<div>{{ $t('login.title') }}</div>
<el-select v-model="value" @change="switchLanguage(value)" class="el-select">
<el-option
v-for="item in language"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<script>
import { locales, i18n, loadLanguageAsync } from "@/untils/i18n-setup"
export default {
data() {
return {
value: this.$i18n.locale, //为了把下拉框的默认值和全局变量的值一致,以此实现载入页面时显示的语言和数据配置一致
language: [
{
value: "en-us",
label: "英文"
},
{
value: "zh-cn",
label: "简体中文"
},
{
value: "es-es",
label: "西班牙语"
}
]
};
},
methods: {
switchLanguage(value) {
console.log(value,this.$i18n.locale);
this.$store.commit('setLocale',value); //vuex
this.$cookies.set('locale',value); // 需要安装 npm i --save cookie-universal-nuxt 代替localstorage
loadLanguageAsync(value).then(() => {
console.log('语言更改成功');
})
},
}
}
</script>
作品来源:https://www.cnblogs.com/juewuzhe/p/15103837.html
再配合vuex middleware
7. 新建 middleware 文件夹 新建locale.js
export default function (app) { //{store,app,route,redirect,params,query,req,res}
let lang = app.$cookies.get('locale');
app.store.commit('setLocale',lang);
}
8.store/index.js
export const state = () => ({
locale:'', //["en-us", "es-es", "zh-cn"]; 要跟 utils/i18n-setup.js相对应
})
export const mutations = {
setLocale(state, value) {
state.locale = value;
// console.log(state.locale)
},
}
9 nuxt.config.js
router:{
middleware:'locale' //在中间件里面 全局设置 每个页面刷新的时候都会是当前选择的语言
}
总结: 以上写法有个问题,当你刷新页面的时候,页面的数据会有一个闪烁的过程, 就比如你最默认是ch的 切换后的语言是en 你刷新之后 页面会先显示默认的 再转换为你所切换的语言;
解决国际化语言 刷新时静态内容闪烁的问题
在默认的布局页面;
layouts/default.vue
<template>
<div v-show="isloaded"> <!-- 切记这里不能用v-if 如果用v-if 查找源代码的时候 就看到代码 相当于SEO没有内容可以抓取;-->
<Header />
<nuxt />
<Footer />
</div>
</template>
<script>
export default {
name:'default',
data(){
return {
isloaded:false
}
},
mounted(){
this.isloaded = true;
}
}
</script>
方式2: 刷新的时候就不会闪烁
1.多语言
{
"home": {
"title": "Welcome",
},
"about": {
"title": "About",
}
}//en-us.json
{
"home": {
"title": "欢迎",
},
"about": {
"title": "有关",
}
}//ch-cn.json
2.中间件 middleware/i18n.js
export default function ({ isHMR, app, store, route, params, error, redirect }) {
const defaultLocale = app.i18n.fallbackLocale
// If middleware is called from hot module replacement, ignore it
if (isHMR) { return }
// Get locale from params
const locale = app.$cookies.get("locale") || store.state.locale || defaultLocale
if (!store.state.locales.includes(locale)) {
return error({ message: '', statusCode: 404 })
}
// Set locale
store.commit('SET_LANG', locale)
app.i18n.locale = store.state.locale
// If route is /<defaultLocale>/... -> redirect to /...
// if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) {
// const toReplace = '^/' + defaultLocale + (route.fullPath.indexOf('/' + defaultLocale + '/') === 0 ? '/' : '')
// const re = new RegExp(toReplace)
// return redirect(
// route.fullPath.replace(re, '/')
// )
// }
if (route.fullPath.indexOf('/' + locale) === -1) {
let pathStr = route.fullPath;
let language = pathStr.substring(1, 2);
pathStr = pathStr.substring(3);// 去掉路由前面的/en /zh
if (store.state.locales.includes(language)) {
return redirect('/' + locale + '' + pathStr)
} else {
return redirect('/' + locale + '' + route.fullPath)
}
// return redirect('/' + locale + '' + route.fullPath)
}
}
// 路由就会展示成 your_domain/en/,当然如果在默认的语言下你不需要展示出 /en/,你也可以换成注释调的部分。
// 路由就会展示成 your_domain/en/,当然如果在默认的语言下你不需要展示出 /en/,你也可以换成注释调的部分。
3.plugins/i18n.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
export default ({ app, store }) => {
// Set i18n instance on app
// This way we can use it in middleware and pages asyncData/fetch
app.i18n = new VueI18n({
locale: app.$cookies.get("locale")||store.state.locale,
fallbackLocale: 'en',
messages: {
'en': require('~/locales/en-us.json'),
'zh': require('~/locales/zh-cn.json'),
'es': require('~/locales/es-es.json')
}
})
app.i18n.path = (link) => {
if (app.i18n.locale === app.i18n.fallbackLocale) {
return `/${link}`
}
return `/${app.i18n.locale}/${link}`
}
}
4.store/index.js
export const state = () => ({
locales: ['en', 'es', 'zh'],//这个定义只能是两个字符 route.fullPath 字符串截图的时候 只截图了3 /+2字符 1.middleware/i18n 2.页面中语言切换的地方
locale: 'en'
})
export const mutations = {
// 此处为设置locale
SET_LANG(state, locale) {
if (state.locales.includes(locale)) {
state.locale = locale
console.log(locale)
}
},
}
5.页面切换语言
<template>
<div class="container">
<div>{{ $t("links.about") }}</div>
<el-select
v-model="value"
@change="changeLanguage(value)"
class="el-select"
>
<el-option
v-for="item in language"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
data() {
return {
subTitle: "", //this.$t("login.subTitle"),
value: this.$i18n.locale, //为了把下拉框的默认值和全局变量的值一致,以此实现载入页面时显示的语言和数据配置一致
language: [
{
value: "en",
label: "英文",
},
{
value: "zh",
label: "简体中文",
},
{
value: "es",
label: "西班牙语",
},
],
};
},
methods: {
changeLanguage(language) {
this.$i18n.locale = language;
this.$store.commit("SET_LANG", language);
this.$cookies.set("locale", language);
let pathStr = this.$route.fullPath;
pathStr = pathStr.substring(3);
this.$router.push(`/`+language + pathStr);//现实切换语言的时候路由跟着变化
},
},
};
</script>
6.安装 cookie-universal-nuxt npm i cookie-universal-nuxt --save
7. 根据上面引入的文件 nuxt.config.js 配置
plugins: [
'@/plugins/i18n.js', //多语言配置文件
],
modules: [
'cookie-universal-nuxt'
],
router:{
middleware:['i18n']
}
nuxt 国际化 的跳转以及传参
注意,path后的路径开头不要加 “ / ”
<!-- 跳转页面 -->
<nuxt-link :to="$i18n.path('home/index')" >跳转</nuxt-link>
<!-- 携带参数 -->
<nuxt-link :to="{path:$i18n.path('home/index'), query:{id:xxx}}" >跳转</nuxt-link>
<script>
// 跳转页面
this.$router.push(this.$i18n.path("home/index"))
// 携带参数
this.$router.push({ path: this.$i18n.path("home/index"), query:{id: 'xxxx'} })
template中使用
<h1>{{ $t('home.title') }}</h1>
data(){
return{
title:this.$t('home.title')
}
}
发现问题,欢迎留言指点~ 谢谢