vue-i18n 实现国际化,支持切换不同语言

需求:后台管理系统,可以实现语言切换

实现过程:用的i18n来实现的语言切换,网上能看到好多模板,根据自己的需求,修改一下即可使用,大概都是差不多的,因为涉及到后端,所以要跟后端协商一致决定去写,我的设计思路是跟着后端设计更改的,如下:

1.语言是后端接口返回的,不是前端写死的(eg:中文、English),由于我的切换语言,设计到了两个地方,一个是登录页面,一个是登录之后的页面,后端不能给一个接口,要区分两个接口给前端,所以关于这个需求,前端自己加了判断(如果你们后端给一个接口,则可忽略我写的判断)

2.根据自己选择的哪一种语言,需要通过接口传给后端,后端会将其存到某个用户表里,这个接口也是两个,也需写判断

3.如果用户是从来没有选择过语言的用户,则前端需要规定默认语言,且要与后端的默认语言保持一致,于是和后端协商一致决定,其默认语言是后端返回的语言的第一个

4.如果后端有选择是哪个语言,我们将其传给了后端,后端讲其存入了用户表,用户登录之后,会在用户接口里,返回给我们,我们将其存 localStorage,这时候,就算用户再次退出到登录页面,我们就可以将用户默认语言做一个判断,判断存入localStorage的language是否有值,如果有值,则登录页面的语言取localStorage的language,如果没有,则还是取后端语言接口返回的第一个值,这样,就可以把用户已经选择过的语言,在登录页面也能进行判断用户习惯

文档: vue-i18n

一.安装vue-i18n 

npm install vue-i18n

二.在mian.js引入

//i18n
import i18n from "@/lang";
Vue.use(Element,{
  size:Cookies.get('size') || 'small',
  i18n:(key,value)=>i18n.t(key,value)
})
new Vue({
  el: '#app',
  router,
  store,
  i18n,
  render: h => h(App)
})

三.在src下创建一个lang文件夹,其中包括en.js、zh.js、index.js文件

1.src/lang/en.js

export default {
  login: {
    username:'username',//用户名
    password:'password',//密码
    code:'code',//验证码
    login:'login',//登录
    logging: 'logging...',//登录...
    storage:'remember the password',//记住密码
  },
  home:{
    welcome:'Welcome to use',//欢迎使用
  },
  route:{
    homepage:'Home page',//首页
    profile:'Profile',//个人中心
    系统管理:"system manage",//系统管理
    系统监控:'system monitor',
    系统工具:"system tools",
    创建运单:"create waybill",
    批量运单:'waybill batch',
    运单管理:"waybill manage",
    审核管理:'audits manage',
    充值管理:'recharge manage',
    失败订单详情:'failed order details',
    运费管理:'freight manage',
    账单管理:'bill manage',
    仓库管理:'warehouse manage',
    用户管理:'user query',
    角色管理:'user query',
    菜单管理:'menu manage',
    部门管理:'dept manage',
    岗位管理:'position manage',
    字典管理:'dictionary manage',
    参数设置:'parameter settings',
    通知公告:'notice announcent',
    日志管理:'log manage',
    操作日志:'operation log',
    登录日志:'login log',
    在线用户:'online users',
    定时任务:'scheduled tasks',
    数据监控:'data monitor',
    服务监控:'service monitor',
    运单审核:'audits order',
    充值审核:'audits recharge',
    客户充值:'customer recharge',
    我的充值:'my recharge',
    基础运费:'basic freight',
    其他附加费:'other surcharges',
    燃油附加费:'fuel surcharge',
    旺季附加费:'peak surcharge',
    全部账单:'bill whole',
    我的账单:'bill my',
    订单详情:'order details',
    仓库配置:'warehouse configuration',
    基础成本价:'basic cost',
    其他成本价:'other cost',
    旺季成本价:'peak cost',
    查询:'query',
    新增:'add',
    修改:'alter',
    导入:'import',
    导出:'export',
    删除:'remove',
    重置密码:'reset passwords',
    仓库:'warehouse',
    批量强退:'batch forcing',
    单条强退:'single strong back',
    众拓网通官网:'Zhongtuo Netcom official website',
    下载失败订单:'download failed order',
    下载面单:'download sheet',
    客户查询:'customer query',
    已取消导出:'export cancelled',
    取消审核中导出:'export cancel audit',
    审核:'audit',
    审核平账:'audit and balance accounts',
    审核平账明细:'review the balance of accounts details',
    充值:'top up',
    充值记录:'recharge record',
    消费记录:'expense calendar',
    补交凭证:'resubmit documents',
    回显:'echo',
    审核明细:'audit detail',
    充值明细:'top-up details',
    失败订单详情查询:'failed order details query',
    复制:'copy',
    基础运费列表:'base freight list',
    客户列表:'customer list',
  },
}

 2.src/lang/zh.js

export default {
  login: {
    username:'用户名',//用户名
    password:'密码',//密码
    code:'验证码',//验证码
    login:'登录',//登录
    logging: '登录...',//登录...
    storage:'记住密码',//记住密码
  },
  home:{
    welcome:'欢迎使用',//欢迎使用
  },
  route:{
    homepage:'首页',//首页
    profile:'个人中心',//个人中心
    系统管理:"系统管理",//系统管理
    系统监控:'系统监控',
    系统工具:"系统工具",
    创建运单:"创建运单",
    批量运单:'批量运单',
    运单管理:"运单管理",
    审核管理:'审核管理',
    充值管理:'充值管理',
    失败订单详情:'失败订单详情',
    运费管理:'运费管理',
    账单管理:'账单管理',
    仓库管理:'仓库管理',
    用户管理:'用户管理',
    角色管理:'角色管理',
    菜单管理:'菜单管理',
    部门管理:'部门管理',
    岗位管理:'岗位管理',
    字典管理:'字典管理',
    参数设置:'参数设置',
    通知公告:'通知公告',
    日志管理:'日志管理',
    操作日志:'操作日志',
    登录日志:'登录日志',
    在线用户:'在线用户',
    定时任务:'定时任务',
    数据监控:'数据监控',
    服务监控:'服务监控',
    运单审核:'运单审核',
    充值审核:'充值审核',
    客户充值:'客户充值',
    我的充值:'我的充值',
    基础运费:'基础运费',
    其他附加费:'其他附加费',
    燃油附加费:'燃油附加费',
    旺季附加费:'旺季附加费',
    全部账单:'全部账单',
    我的账单:'我的账单',
    订单详情:'订单详情',
    仓库配置:'仓库配置',
    基础成本价:'基础成本价',
    其他成本价:'其他成本价',
    旺季成本价:'旺季成本价',
    查询:'查询',
    新增:'新增',
    修改:'修改',
    导入:'导入',
    导出:'导出',
    删除:'删除',
    重置密码:'重置密码',
    仓库:'仓库',
    批量强退:'批量强退',
    单条强退:'单条强退',
    众拓网通官网:'众拓网通官网',
    下载失败订单:'下载失败订单',
    下载面单:'下载面单',
    客户查询:'客户查询',
    已取消导出:'已取消导出',
    取消审核中导出:'取消审核中导出',
    审核:'审核',
    审核平账:'审核平账',
    审核平账明细:'审核平账明细',
    充值:'充值',
    充值记录:'充值记录',
    消费记录:'消费记录',
    补交凭证:'补交凭证s',
    回显:'回显',
    审核明细:'审核明细',
    充值明细:'充值明细',
    失败订单详情查询:'失败订单详情查询',
    复制:'复制',
    基础运费列表:'基础运费列表',
    客户列表:'客户列表',
  },
}

  3.src/lang/index.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
import enLocale from './en'
import zhLocale from './zh'

Vue.use(VueI18n)

const messages = {
  en: {
    ...enLocale,
    ...elementEnLocale
  },
  zh: {
    ...zhLocale,
    ...elementZhLocale
  }
}
export function getLanguage() {
  const chooseLanguage = Cookies.get('language')
  if (chooseLanguage) return chooseLanguage
  return 'en'
}
const i18n = new VueI18n({
  locale: getLanguage(),
  messages
})

export default i18n

三.在src/components下创建到LangSelect/index.vue文件(语言切换组件)




四.在src/store/modules/app.js 里将language存入vuex和cookie

import Cookies from 'js-cookie'
import { getLanguage } from '@/lang/index'

const state = {
  sidebar: {
    opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
    withoutAnimation: false,
    hide: false
  },
  device: 'desktop',
  language: getLanguage(),
  size: Cookies.get('size') || 'medium'
}

const mutations = {
  TOGGLE_SIDEBAR: state => {
    if (state.sidebar.hide) {
      return false;
    }
    state.sidebar.opened = !state.sidebar.opened
    state.sidebar.withoutAnimation = false
    if (state.sidebar.opened) {
      Cookies.set('sidebarStatus', 1)
    } else {
      Cookies.set('sidebarStatus', 0)
    }
  },
  CLOSE_SIDEBAR: (state, withoutAnimation) => {
    Cookies.set('sidebarStatus', 0)
    state.sidebar.opened = false
    state.sidebar.withoutAnimation = withoutAnimation
  },
  TOGGLE_DEVICE: (state, device) => {
    state.device = device
  },
//语言
  SET_LANGUAGE: (state, language) => {
    state.language = language
    Cookies.set('language', language)
  },
  SET_SIZE: (state, size) => {
    state.size = size
    Cookies.set('size', size)
  },
  SET_SIDEBAR_HIDE: (state, status) => {
    state.sidebar.hide = status
  }
}

const actions = {
  toggleSideBar({ commit }) {
    commit('TOGGLE_SIDEBAR')
  },
  closeSideBar({ commit }, { withoutAnimation }) {
    commit('CLOSE_SIDEBAR', withoutAnimation)
  },
  toggleDevice({ commit }, device) {
    commit('TOGGLE_DEVICE', device)
  },
//语言
  setLanguage({ commit }, language) {
    commit('SET_LANGUAGE', language)
  },
  setSize({ commit }, size) {
    commit('SET_SIZE', size)
  },
  toggleSideBarHide({ commit }, status) {
    commit('SET_SIDEBAR_HIDE', status)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

五.src/modules/user.js,将后端用户信息接口返回的language存入localStorage里

import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'

const user = {
  state: {
    token: getToken(),
    name: '',
    avatar: '',
    roles: [],
    permissions: [],
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, name) => {
      state.name = name
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_PERMISSIONS: (state, permissions) => {
      state.permissions = permissions
    },
  },

  actions: {
    // 登录
    Login({ commit }, userInfo) {
      const username = userInfo.username.trim()
      const password = userInfo.password
      const code = userInfo.code
      const uuid = userInfo.uuid
      //语言
      const languageId=userInfo.languageId
      return new Promise((resolve, reject) => {
        login(username, password, code, uuid,languageId).then(res => {
          setToken(res.token)
          commit('SET_TOKEN', res.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 获取用户信息
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getInfo(state.token).then(res => {
          const user = res.user
          const avatar = user.avatar == "" ? require("@/assets/image/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
          if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
            commit('SET_ROLES', res.roles)
            commit('SET_PERMISSIONS', res.permissions)
            sessionStorage.setItem('infoCustomers',JSON.stringify(res.customers))
            sessionStorage.setItem('infouser',JSON.stringify(res.user.roles))
            //注:用户已进入页面,调用到用户接口,将用户接口里面的语言存储到localStorage,可以方便用户在登录页面的时候判断语言是中文还是英文(登录页面语言应与user接口保持一直)
            localStorage.setItem('language',JSON.stringify(res.user.language.language).replace(/\"/g, ""))
          } else {
            commit('SET_ROLES', ['ROLE_DEFAULT'])
          }
          commit('SET_NAME', user.userName)
          commit('SET_AVATAR', avatar)
          resolve(res)
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 退出系统
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          commit('SET_PERMISSIONS', [])
          removeToken()
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 前端 登出
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        removeToken()
        resolve()
      })
    }
  }
}

export default user

 六.登录页面

 效果图:

1.en:

vue-i18n 实现国际化,支持切换不同语言_第1张图片

2.English:

 vue-i18n 实现国际化,支持切换不同语言_第2张图片



  七.在utils里面新建一个i18n.js

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

 七.根据语言的切换,面包屑的语言也随之更新,src/components/Breadcrumb文件里

1.zh: 

 

2.en: 

vue-i18n 实现国际化,支持切换不同语言_第3张图片 






八.src\layout\components\Sidebar\SidebarItem.vue文件

1.zh                                                                                  

vue-i18n 实现国际化,支持切换不同语言_第4张图片

2.en

vue-i18n 实现国际化,支持切换不同语言_第5张图片

我用的是若依后台管理系统框架,对于路由是后端接口返回的,所以,路由语言切换只有两种实现方式 ,后端接口返回,缺点,每次新增修改路由,后端都要在数据库里面新增、修改两种语言,较为麻烦,所以路由的语言切换就纯前端进行控制。




 需要注意的是,对于首页,是前端写的路由,其余的页面路由都是后端接口返回的,所以在前端,针对首页,需要改的是router/index.js

vue-i18n 实现国际化,支持切换不同语言_第6张图片

九.菜单管理,和路由同理,都是后端接口返回,接口返回的语言切换,纯前端处理

1.zh

2.en 

 

 十.样式处理,可能中文的长度很短,英文长度很长,样式就会错乱,对于这种情况进行处理

  
      
        
          

            
              
            
          
        
      
      
    
getLabelWidth(){
      let labelWidth = '80px';
      if(this.language=='en'){
        labelWidth = '150px';
      }
      return labelWidth;
    },

十一.对于校验的地方,语言切换之后,并不会再次触发校验的语言切换 ,关于这个点,我是进行了监听,语言是否改变,如果语言改变了,我就再次触发校验,缺点,每次切换语言就会出发校验,并不是,我点击了某个提交按钮,进行的校验触发,例如我上面写的登录页面上的校验

vue-i18n 实现国际化,支持切换不同语言_第7张图片

 以上就是整个实现过程啦,可能有点地方忘记写了,等想到了,再进行完善

你可能感兴趣的:(vue.js,javascript,前端)