nuxt + elementUI 多语言 国际化

这里一共讲述两种方式 亲测过的

方式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')  

}

}

 

 

发现问题,欢迎留言指点~  谢谢

posted @ 2022-05-10 16:28  elliot1004  阅读(1477)  评论(0)    收藏  举报