vue-admin-template 各种功能修改

本文介绍如何在Vue项目中实现多语言支持,包括安装vue-i18n插件、配置多语言文件、实现语言切换功能等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、添加国际化

先看效果

        中文

         英文

 1、安装vue-i18n

        npm install vue-i18n@8.24.5 -S  (我这里node版本10.24.2)

2、新增文件

        1)在src目录下新增lang文件夹,并在lang文件夹下新建如下文件

        

        index.js

        代码如下:

// 进行多语言支持配置
import Vue from 'vue' // 引入Vue
import VueI18n from 'vue-i18n' // 引入国际化的插件包
import Cookies from 'js-cookie' // 引入 Cookies 保存当前默认语言选项

import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui 英文包
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui 中文包

// 自定义的中英文配置
import enLocale from './en'
import zhLocale from './zh'


Vue.use(VueI18n); // 全局注册国际化包

// 创建国际化插件的实例
const i18n = new VueI18n({
  // 指定语言类型 zh表示中文  en表示英文 set locale 设置默认初始化的语言 i18n
  locale: Cookies.get('language') || 'zh',
  // 将将elementUI语言包 和自定义语言包 加入到插件语言数据里 set locale messages
  messages: {
    // 英文环境下的语言数据
    en: {
      ...enLocale,
      ...elementEnLocale
    },
    // 中文环境下的语言数据
    zh: {
      ...zhLocale,
      ...elementZhLocale
    }
  }
});

export default i18n

 zh.js和en.js分别对应不同的语言,这里仅中文和英文,可自行添加别的语言

         2)在src下的util文件夹新建i8n.js文件

        

        代码如下

// 翻译router.meta。标题,用于面包屑侧边栏tagsview
export function generateTitle(title) {
  const hasKey = this.$te('route.' + title)

  if (hasKey) {
    // $t :this method from vue-i18n, inject in @/lang/index.js
    return this.$t('route.' + title)
  }
  return title
}

         

3、配置i8n

        1) 在main.js文件中添加如下内容

        

        代码如下

//国际化
import i18n from './lang'

Vue.use(ElementUI,{
  i18n: (key,value) => i18n.t(key,value)
})

         2)修改store文件夹

        修改modules文件夹下的app.js文件,添加如下内容

        

        

         代码如下

  language: Cookies.get('language') || 'zh'


  SET_LANGUAGE: (state, language) => {
    state.language = language
    Cookies.set('language', language)
  }



  setLanguage({
    commit
  }, language) {
    commit('SET_LANGUAGE', language)
  },

         getters.js文件中添加如下内容

         代码如下

  language: state => state.app.language,
  size: state => state.app.size,

4、应用

       1) 在topheader中加入选择下拉框(可自行选择地方)

        在layout-components-Navbar.vue中添加如下内容

        

         代码如下

      <template>
        <lang-select class="right-menu-item hover-effect"/>
      </template>

        2)添加语言选择下拉框组件

        在src components文件夹新建   LangSelect-index.vue文件

        

        代码如下

                 这里加了一些图片样式,可自行修改

<template>
  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
    <div style="margin-right: 15px">
      <img src="../../assets/language.png" style="width: 20px;height: 20px;margin-right: 8px;margin-top: 2px"/>
    </div>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item :disabled="language==='zh'" command="zh">
        <div>
          <img src="../../assets/chineseflag.png" style="width: 15px;margin-right: 8px"/>
          中文
        </div>
      </el-dropdown-item>
      <el-dropdown-item :disabled="language==='en'" command="en">
        <div>
          <img src="../../assets/english.png" style="width: 15px;margin-right: 8px"/>
          English
        </div>
      </el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</template>

<script>
export default {
  name: "LangSelect",
  computed: {
    language() {
      return this.$store.getters.language
    }
  },
  data(){
    return{

    }
  },
  created() {
  },
  watch:{

  },
  methods: {
    handleSetLanguage(lang) {
      this.$i18n.locale = lang;
      this.$store.dispatch('app/setLanguage', lang)
      this.$message.success('切换语言成功!!')
    }
  }
}
</script>

<style>
</style>

         至此大致国际化功能已经实现,在页面中通过 $t('') 来渲染即可

        可使用{{ }}或者v-bind方式实现

         

5、面包屑,侧边菜单栏转换

        1)面包屑 (这里面包屑的实现就不讲解了,可自行查阅)

        修改如下内容

         代码如下

<template>
  <el-breadcrumb class="app-breadcrumb" separator="/">
    <transition-group name="breadcrumb">
      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
        <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
        <a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
      </el-breadcrumb-item>
    </transition-group>
  </el-breadcrumb>
</template>

<script>
import pathToRegexp from 'path-to-regexp'
import { generateTitle } from '@/utils/i18n'
export default {
  data() {
    return {
      levelList: null
    }
  },
  watch: {
    $route() {
      this.getBreadcrumb()
    }
  },
  created() {
    this.getBreadcrumb()
  },
  methods: {
    generateTitle,
    getBreadcrumb() {
      // only show routes with meta.title
      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
      const first = matched[0]

      if (!this.isDashboard(first)) {
        matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
      }

      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
    },
    isDashboard(route) {
      const name = route && route.name
      if (!name) {
        return false
      }
      return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
    },
    pathCompile(path) {
      // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
      const { params } = this.$route
      var toPath = pathToRegexp.compile(path)
      return toPath(params)
    },
    handleLink(item) {
      const { redirect, path } = item
      if (redirect) {
        this.$router.push(redirect)
        return
      }
      this.$router.push(this.pathCompile(path))
    }
  }
}
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  font-size: 14px;
  line-height: 50px;
  margin-left: 8px;

  .no-redirect {
    color: #97a8be;
    cursor: text;
  }
}
</style>

        

        2)侧边菜单栏

        修改如下内容

         代码如下

<template>
  <div v-if="!item.hidden">
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" />
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="generateTitle(item.meta.title)" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
import { generateTitle } from '@/utils/i18n'

export default {
  name: 'SidebarItem',
  components: { Item, AppLink },
  mixins: [FixiOSBug],
  props: {
    // route object
    item: {
      type: Object,
      required: true
    },
    isNest: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String,
      default: ''
    }
  },
  data() {
    // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
    // TODO: refactor with render function
    this.onlyOneChild = null
    return {}
  },
  methods: {
    generateTitle,
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          this.onlyOneChild = item
          return true
        }
      })

      // When there is only one child router, the child router is displayed by default
      if (showingChildren.length === 1) {
        return true
      }

      // Show parent if there are no child router to display
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    resolvePath(routePath) {
      if (isExternal(routePath)) {
        return routePath
      }
      if (isExternal(this.basePath)) {
        return this.basePath
      }
      return path.resolve(this.basePath, routePath)
    }
  }
}
</script>

        英文的翻译名称与路由中的meta中的title一致

        只需在route中编写,因为在i8n.js中已经做了处理  如图

想要获取当前的语言可以通过 this.$store.getters.language 来获取,

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值