From 88f1f8bd5b85d890f7f2b251a93708e74f8b6bfb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=AB=98=E6=96=B0=E5=AE=87?= <gaoxinyu@uwin-link.com>
Date: Sat, 18 Sep 2021 15:33:33 +0800
Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=A2=9E=E5=8A=A0i8n=E5=9B=BD?=
 =?UTF-8?q?=E9=99=85=E5=8C=96=E6=8F=92=E4=BB=B6=EF=BC=9B=E5=A2=9E=E5=8A=A0?=
 =?UTF-8?q?=E8=AF=AD=E8=A8=80=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD=EF=BC=9B?=
 =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=E7=A4=BA=E4=BE=8B=E9=A1=B5=E9=9D=A2?=
 =?UTF-8?q?=EF=BC=9A=E7=99=BB=E5=BD=95=E3=80=81=E7=94=A8=E6=88=B7=E7=AE=A1?=
 =?UTF-8?q?=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ruoyi-ui/package.json                         |   1 +
 .../src/components/LanguageSelect/index.vue   |  53 +++++
 ruoyi-ui/src/i18n/i18n.js                     |  40 ++++
 ruoyi-ui/src/i18n/langs/en.js                 |  50 +++++
 ruoyi-ui/src/i18n/langs/zh.js                 |  50 +++++
 ruoyi-ui/src/layout/components/Navbar.vue     |   9 +-
 ruoyi-ui/src/main.js                          |   3 +-
 ruoyi-ui/src/store/getters.js                 |   1 +
 ruoyi-ui/src/store/modules/app.js             |  12 +-
 ruoyi-ui/src/views/login.vue                  | 206 ++++++++++++------
 ruoyi-ui/src/views/system/user/index.vue      |  58 ++---
 11 files changed, 388 insertions(+), 95 deletions(-)
 create mode 100644 ruoyi-ui/src/components/LanguageSelect/index.vue
 create mode 100644 ruoyi-ui/src/i18n/i18n.js
 create mode 100644 ruoyi-ui/src/i18n/langs/en.js
 create mode 100644 ruoyi-ui/src/i18n/langs/zh.js

diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index 9048f5a4d..73538403b 100644
--- a/ruoyi-ui/package.json
+++ b/ruoyi-ui/package.json
@@ -55,6 +55,7 @@
     "vue": "2.6.12",
     "vue-count-to": "1.0.13",
     "vue-cropper": "0.5.5",
+    "vue-i18n": "^8.25.0",
     "vue-meta": "^2.4.0",
     "vue-router": "3.4.9",
     "vuedraggable": "2.24.3",
diff --git a/ruoyi-ui/src/components/LanguageSelect/index.vue b/ruoyi-ui/src/components/LanguageSelect/index.vue
new file mode 100644
index 000000000..e17601a6e
--- /dev/null
+++ b/ruoyi-ui/src/components/LanguageSelect/index.vue
@@ -0,0 +1,53 @@
+<template>
+  <el-dropdown
+    trigger="click"
+    @command="handleSetLanguage"
+  >
+    <div>
+      <svg-icon
+        class-name="size-icon"
+        icon-class="language"
+      />
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item
+        v-for="item of languageOptions"
+        :key="item.value"
+        :disabled="lang===item.value"
+        :command="item.value"
+      >
+        {{
+          item.label }}
+      </el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      languageOptions: [
+        { label: '中文', value: 'zh' },
+        { label: 'English', value: 'en' }
+      ]
+    }
+  },
+  computed: {
+    lang() {
+      return this.$store.getters.lang
+    }
+  },
+  methods: {
+    handleSetLanguage(lang) {
+      this.$store.dispatch('app/setLang', lang)
+      this.$i18n.locale = lang
+      const msg = lang == 'zh' ? '语言切换成功' : 'Switch Language Success'
+      this.$message({
+        message: msg,
+        type: 'success'
+      })
+    }
+  }
+}
+</script>
diff --git a/ruoyi-ui/src/i18n/i18n.js b/ruoyi-ui/src/i18n/i18n.js
new file mode 100644
index 000000000..c7f647d24
--- /dev/null
+++ b/ruoyi-ui/src/i18n/i18n.js
@@ -0,0 +1,40 @@
+import Vue from 'vue'
+import Cookies from 'js-cookie'
+import VueI18n from 'vue-i18n'
+import locale from 'element-ui/lib/locale';
+import zh from './langs/zh'
+import en from './langs/en'
+import enLocale from 'element-ui/lib/locale/lang/en'
+import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
+
+
+Vue.use(VueI18n)
+
+const messages = {
+  en: Object.assign(en, enLocale),
+  zh: Object.assign(zh, zhLocale)
+}
+
+export function getLanguage() {
+  const chooseLanguage = Cookies.get('lang')
+  if (chooseLanguage) return chooseLanguage
+
+  const language = (navigator.language || navigator.browserLanguage).toLowerCase()
+  const locales = Object.keys(messages)
+  for (const locale of locales) {
+    if (language.indexOf(locale) > -1) {
+      return locale
+    }
+  }
+  return 'en'
+}
+
+const i18n = new VueI18n({
+  locale: getLanguage(),
+  messages
+})
+
+
+locale.i18n((key, value) => i18n.t(key, value)) //为了实现element插件的多语言切换
+
+export default i18n
diff --git a/ruoyi-ui/src/i18n/langs/en.js b/ruoyi-ui/src/i18n/langs/en.js
new file mode 100644
index 000000000..189abb6af
--- /dev/null
+++ b/ruoyi-ui/src/i18n/langs/en.js
@@ -0,0 +1,50 @@
+const bt = {
+  search: 'Search',
+  reset: 'Reset',
+  create: 'Create',
+  edit: 'Edit',
+  delete: 'Delete',
+  import: 'Import',
+  export: 'Export',
+  more: 'More',
+  resetPassWord: 'ResetPassWord',
+  assigningRoles: 'AssigningRoles',
+  register: 'Register'
+}
+
+const hint = {
+  inputDeptName: 'Please enter the department name',
+  inputUserName: 'Please enter the user name',
+  inputPhonenumber: 'Please enter the phone number',
+  selectUserStatus: 'UserStatus',
+  startDate: 'StartDate',
+  endDate: 'EndDate',
+  operate: 'Operate',
+  inputPassword: 'Please enter the password',
+  inputCode: 'Please enter the verification code'
+}
+
+const system = {
+  user: {
+    managementSystem: 'RuoYi Management System',
+    userId: 'UserId',
+    userName: 'UserName',
+    passWord: 'PassWord',
+    checkCode: 'CheckCode',
+    rememberMe: 'Remember Me',
+    login: 'Login',
+    loggingIn: 'Logging in',
+    phonenumber: 'Phonenumber',
+    status: 'Status',
+    createDate: 'CreateDate',
+    nickName: 'NickName',
+    deptName: 'DeptName',
+    createTime: 'CreateTime'
+  }
+}
+
+module.exports = {
+  bt,
+  hint,
+  system,
+}
diff --git a/ruoyi-ui/src/i18n/langs/zh.js b/ruoyi-ui/src/i18n/langs/zh.js
new file mode 100644
index 000000000..3d5c49981
--- /dev/null
+++ b/ruoyi-ui/src/i18n/langs/zh.js
@@ -0,0 +1,50 @@
+const bt = {
+  search: '搜索',
+  reset: '重置',
+  create: '新增',
+  edit: '修改',
+  delete: '删除',
+  import: '导入',
+  export: '导出',
+  more: '更多',
+  resetPassWord: '重置密码',
+  assigningRoles: '分配角色',
+  register: '注册'
+}
+
+const hint = {
+  inputDeptName: '请输入部门名称',
+  inputUserName: '请输入用户名',
+  inputPhonenumber: '请输入手机号码',
+  selectUserStatus: '用户状态',
+  startDate: '开始日期',
+  endDate: '结束日期',
+  operate: '操作',
+  inputPassword: '请输入密码',
+  inputCode: '请输入验证码'
+}
+
+const system = {
+  user: {
+    managementSystem: '若依后台管理系统',
+    userId: '用户编号',
+    userName: '用户名',
+    passWord: '密码',
+    checkCode: '验证码',
+    rememberMe: '记住我',
+    login: '登 录',
+    loggingIn: '登 录 中...',
+    phonenumber: '手机号码',
+    status: '状态',
+    createDate: '创建日期',
+    nickName: '用户昵称',
+    deptName: '部门',
+    createTime: '创建时间'
+  }
+}
+
+module.exports = {
+  bt,
+  hint,
+  system,
+}
diff --git a/ruoyi-ui/src/layout/components/Navbar.vue b/ruoyi-ui/src/layout/components/Navbar.vue
index 67a53ab67..e0b8128ac 100644
--- a/ruoyi-ui/src/layout/components/Navbar.vue
+++ b/ruoyi-ui/src/layout/components/Navbar.vue
@@ -22,7 +22,10 @@
         <el-tooltip content="布局大小" effect="dark" placement="bottom">
           <size-select id="size-select" class="right-menu-item hover-effect" />
         </el-tooltip>
-
+	<language-select
+          id="language"
+          class="right-menu-item hover-effect"
+        />
       </template>
 
       <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
@@ -56,6 +59,7 @@ import SizeSelect from '@/components/SizeSelect'
 import Search from '@/components/HeaderSearch'
 import RuoYiGit from '@/components/RuoYi/Git'
 import RuoYiDoc from '@/components/RuoYi/Doc'
+import LanguageSelect from '@/components/LanguageSelect'
 
 export default {
   components: {
@@ -66,7 +70,8 @@ export default {
     SizeSelect,
     Search,
     RuoYiGit,
-    RuoYiDoc
+    RuoYiDoc,
+    LanguageSelect
   },
   computed: {
     ...mapGetters([
diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js
index e055dd411..6c04bde59 100644
--- a/ruoyi-ui/src/main.js
+++ b/ruoyi-ui/src/main.js
@@ -1,7 +1,7 @@
 import Vue from 'vue'
 
 import Cookies from 'js-cookie'
-
+import i18n from './i18n/i18n'
 import Element from 'element-ui'
 import './assets/styles/element-variables.scss'
 
@@ -87,5 +87,6 @@ new Vue({
   el: '#app',
   router,
   store,
+  i18n,
   render: h => h(App)
 })
diff --git a/ruoyi-ui/src/store/getters.js b/ruoyi-ui/src/store/getters.js
index 8d723813b..9011818ab 100644
--- a/ruoyi-ui/src/store/getters.js
+++ b/ruoyi-ui/src/store/getters.js
@@ -1,6 +1,7 @@
 const getters = {
   sidebar: state => state.app.sidebar,
   size: state => state.app.size,
+  lang: state => state.app.lang,
   device: state => state.app.device,
   visitedViews: state => state.tagsView.visitedViews,
   cachedViews: state => state.tagsView.cachedViews,
diff --git a/ruoyi-ui/src/store/modules/app.js b/ruoyi-ui/src/store/modules/app.js
index c8d8ee91e..35d4b5916 100644
--- a/ruoyi-ui/src/store/modules/app.js
+++ b/ruoyi-ui/src/store/modules/app.js
@@ -6,7 +6,8 @@ const state = {
     withoutAnimation: false
   },
   device: 'desktop',
-  size: Cookies.get('size') || 'medium'
+  size: Cookies.get('size') || 'medium',
+  lang: Cookies.get('lang') || 'zh'
 }
 
 const mutations = {
@@ -30,6 +31,10 @@ const mutations = {
   SET_SIZE: (state, size) => {
     state.size = size
     Cookies.set('size', size)
+  },
+  SET_LANG: (state, lang) => {
+    state.lang = lang
+    Cookies.set('lang', lang)
   }
 }
 
@@ -45,6 +50,11 @@ const actions = {
   },
   setSize({ commit }, size) {
     commit('SET_SIZE', size)
+  },
+  setLang({
+    commit
+  }, lang) {
+    commit('SET_LANG', lang)
   }
 }
 
diff --git a/ruoyi-ui/src/views/login.vue b/ruoyi-ui/src/views/login.vue
index 255eafca0..023bb0685 100644
--- a/ruoyi-ui/src/views/login.vue
+++ b/ruoyi-ui/src/views/login.vue
@@ -1,10 +1,32 @@
 <template>
   <div class="login">
-    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
-      <h3 class="title">若依后台管理系统</h3>
+    <el-form
+      ref="loginForm"
+      :model="loginForm"
+      :rules="loginRules"
+      class="login-form"
+    >
+      <div class="head">
+        <h3 class="title">{{$t('system.user.managementSystem')}}
+        </h3>
+        <language-select
+          id="language"
+          class="right-menu-item hover-effect"
+          style="height: 20px;"
+        />
+      </div>
       <el-form-item prop="username">
-        <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
-          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
+        <el-input
+          v-model="loginForm.username"
+          type="text"
+          auto-complete="off"
+          :placeholder="$t('system.user.userName')"
+        >
+          <svg-icon
+            slot="prefix"
+            icon-class="user"
+            class="el-input__icon input-icon"
+          />
         </el-input>
       </el-form-item>
       <el-form-item prop="password">
@@ -12,27 +34,46 @@
           v-model="loginForm.password"
           type="password"
           auto-complete="off"
-          placeholder="密码"
+          :placeholder="$t('system.user.passWord')"
           @keyup.enter.native="handleLogin"
+          show-password
         >
-          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+          <svg-icon
+            slot="prefix"
+            icon-class="password"
+            class="el-input__icon input-icon"
+          />
         </el-input>
       </el-form-item>
-      <el-form-item prop="code" v-if="captchaOnOff">
+      <el-form-item
+        prop="code"
+        v-if="captchaOnOff"
+      >
         <el-input
           v-model="loginForm.code"
           auto-complete="off"
-          placeholder="验证码"
+          :placeholder="$t('system.user.checkCode')"
           style="width: 63%"
           @keyup.enter.native="handleLogin"
         >
-          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
+          <svg-icon
+            slot="prefix"
+            icon-class="validCode"
+            class="el-input__icon input-icon"
+          />
         </el-input>
         <div class="login-code">
-          <img :src="codeUrl" @click="getCode" class="login-code-img"/>
+          <img
+            :src="codeUrl"
+            @click="getCode"
+            class="login-code-img"
+          />
         </div>
       </el-form-item>
-      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
+      <el-checkbox
+        v-model="loginForm.rememberMe"
+        style="margin:0px 0px 25px 0px;"
+      >{{$t('system.user.rememberMe')}}</el-checkbox>
       <el-form-item style="width:100%;">
         <el-button
           :loading="loading"
@@ -41,11 +82,17 @@
           style="width:100%;"
           @click.native.prevent="handleLogin"
         >
-          <span v-if="!loading">登 录</span>
-          <span v-else>登 录 中...</span>
+          <span v-if="!loading">{{$t('system.user.login')}}</span>
+          <span v-else>{{$t('system.user.loggingIn')}}</span>
         </el-button>
-        <div style="float: right;" v-if="register">
-          <router-link class="link-type" :to="'/register'">立即注册</router-link>
+        <div
+          style="float: right;"
+          v-if="register"
+        >
+          <router-link
+            class="link-type"
+            :to="'/register'"
+          >{{$t('bt.register')}}</router-link>
         </div>
       </el-form-item>
     </el-form>
@@ -57,31 +104,24 @@
 </template>
 
 <script>
-import { getCodeImg } from "@/api/login";
-import Cookies from "js-cookie";
+import { getCodeImg } from '@/api/login'
+import Cookies from 'js-cookie'
 import { encrypt, decrypt } from '@/utils/jsencrypt'
+import LanguageSelect from '@/components/LanguageSelect'
 
 export default {
-  name: "Login",
+  name: 'Login',
+  components: { LanguageSelect },
   data() {
     return {
-      codeUrl: "",
-      cookiePassword: "",
+      codeUrl: '',
+      cookiePassword: '',
       loginForm: {
-        username: "admin",
-        password: "admin123",
+        username: 'admin',
+        password: 'admin123',
         rememberMe: false,
-        code: "",
-        uuid: ""
-      },
-      loginRules: {
-        username: [
-          { required: true, trigger: "blur", message: "请输入您的账号" }
-        ],
-        password: [
-          { required: true, trigger: "blur", message: "请输入您的密码" }
-        ],
-        code: [{ required: true, trigger: "change", message: "请输入验证码" }]
+        code: '',
+        uuid: ''
       },
       loading: false,
       // 验证码开关
@@ -89,66 +129,104 @@ export default {
       // 注册开关
       register: false,
       redirect: undefined
-    };
+    }
   },
   watch: {
     $route: {
       handler: function(route) {
-        this.redirect = route.query && route.query.redirect;
+        this.redirect = route.query && route.query.redirect
       },
       immediate: true
     }
   },
+  computed: {
+    loginRules() {
+      const that = this
+      const rules = {
+        username: [
+          {
+            required: true,
+            trigger: 'blur',
+            message: that.$t('hint.inputUserName')
+          }
+        ],
+        password: [
+          {
+            required: true,
+            trigger: 'blur',
+            message: that.$t('hint.inputPassword')
+          }
+        ],
+        code: [
+          {
+            required: true,
+            trigger: 'change',
+            message: that.$t('hint.inputCode')
+          }
+        ]
+      }
+      return rules
+    }
+  },
   created() {
-    this.getCode();
-    this.getCookie();
+    this.getCode()
+    this.getCookie()
   },
   methods: {
     getCode() {
       getCodeImg().then(res => {
-        this.captchaOnOff = res.captchaOnOff === undefined ? true : res.captchaOnOff;
+        this.captchaOnOff =
+          res.captchaOnOff === undefined ? true : res.captchaOnOff
         if (this.captchaOnOff) {
-          this.codeUrl = "data:image/gif;base64," + res.img;
-          this.loginForm.uuid = res.uuid;
+          this.codeUrl = 'data:image/gif;base64,' + res.img
+          this.loginForm.uuid = res.uuid
         }
-      });
+      })
     },
     getCookie() {
-      const username = Cookies.get("username");
-      const password = Cookies.get("password");
+      const username = Cookies.get('username')
+      const password = Cookies.get('password')
       const rememberMe = Cookies.get('rememberMe')
       this.loginForm = {
         username: username === undefined ? this.loginForm.username : username,
-        password: password === undefined ? this.loginForm.password : decrypt(password),
+        password:
+          password === undefined ? this.loginForm.password : decrypt(password),
         rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
-      };
+      }
     },
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
         if (valid) {
-          this.loading = true;
+          this.loading = true
           if (this.loginForm.rememberMe) {
-            Cookies.set("username", this.loginForm.username, { expires: 30 });
-            Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
-            Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
+            Cookies.set('username', this.loginForm.username, { expires: 30 })
+            Cookies.set('password', encrypt(this.loginForm.password), {
+              expires: 30
+            })
+            Cookies.set('rememberMe', this.loginForm.rememberMe, {
+              expires: 30
+            })
           } else {
-            Cookies.remove("username");
-            Cookies.remove("password");
-            Cookies.remove('rememberMe');
+            Cookies.remove('username')
+            Cookies.remove('password')
+            Cookies.remove('rememberMe')
           }
-          this.$store.dispatch("Login", this.loginForm).then(() => {
-            this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
-          }).catch(() => {
-            this.loading = false;
-            if (this.captchaOnOff) {
-              this.getCode();
-            }
-          });
+          this.$store
+            .dispatch('Login', this.loginForm)
+            .then(() => {
+              this.$router.push({ path: this.redirect || '/' }).catch(() => {})
+            })
+            .catch(() => {
+              this.loading = false
+              if (this.captchaOnOff) {
+                this.getCode()
+              }
+            })
         }
-      });
+      })
     }
   }
-};
+}
 </script>
 
 <style rel="stylesheet/scss" lang="scss">
@@ -160,6 +238,10 @@ export default {
   background-image: url("../assets/images/login-background.jpg");
   background-size: cover;
 }
+.head {
+  display: flex;
+}
+
 .title {
   margin: 0px auto 30px auto;
   text-align: center;
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 9dea91d1a..cd33b5f15 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -6,7 +6,7 @@
         <div class="head-container">
           <el-input
             v-model="deptName"
-            placeholder="请输入部门名称"
+            :placeholder="$t('hint.inputDeptName')"
             clearable
             size="small"
             prefix-icon="el-icon-search"
@@ -28,17 +28,17 @@
       <!--用户数据-->
       <el-col :span="20" :xs="24">
         <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-          <el-form-item label="用户名称" prop="userName">
+          <el-form-item :label="$t('system.user.userName')" prop="userName" label-width='100px'>
             <el-input
               v-model="queryParams.userName"
-              placeholder="请输入用户名称"
+              :placeholder="$t('hint.inputUserName')"
               clearable
               size="small"
               style="width: 240px"
               @keyup.enter.native="handleQuery"
             />
           </el-form-item>
-          <el-form-item label="手机号码" prop="phonenumber">
+          <el-form-item :label="$t('system.user.phonenumber')" prop="phonenumber" label-width='100px'>
             <el-input
               v-model="queryParams.phonenumber"
               placeholder="请输入手机号码"
@@ -48,10 +48,10 @@
               @keyup.enter.native="handleQuery"
             />
           </el-form-item>
-          <el-form-item label="状态" prop="status">
+          <el-form-item :label="$t('system.user.status')" prop="status">
             <el-select
               v-model="queryParams.status"
-              placeholder="用户状态"
+              :placeholder="$t('hint.selectUserStatus')"
               clearable
               size="small"
               style="width: 240px"
@@ -64,7 +64,7 @@
               />
             </el-select>
           </el-form-item>
-          <el-form-item label="创建时间">
+          <el-form-item :label="$t('system.user.createDate')" label-width='100px'>
             <el-date-picker
               v-model="dateRange"
               size="small"
@@ -72,13 +72,13 @@
               value-format="yyyy-MM-dd"
               type="daterange"
               range-separator="-"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
+              :start-placeholder="$t('hint.startDate')"
+              :end-placeholder="$t('hint.endDate')"
             ></el-date-picker>
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{$t('bt.search')}}</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{$t('bt.reset')}}</el-button>
           </el-form-item>
         </el-form>
 
@@ -91,7 +91,7 @@
               size="mini"
               @click="handleAdd"
               v-hasPermi="['system:user:add']"
-            >新增</el-button>
+            >{{$t('bt.create')}}</el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button
@@ -102,7 +102,7 @@
               :disabled="single"
               @click="handleUpdate"
               v-hasPermi="['system:user:edit']"
-            >修改</el-button>
+            >{{$t('bt.edit')}}</el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button
@@ -113,7 +113,7 @@
               :disabled="multiple"
               @click="handleDelete"
               v-hasPermi="['system:user:remove']"
-            >删除</el-button>
+            >{{$t('bt.delete')}}</el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button
@@ -123,7 +123,7 @@
               size="mini"
               @click="handleImport"
               v-hasPermi="['system:user:import']"
-            >导入</el-button>
+            >{{$t('bt.import')}}</el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button
@@ -134,19 +134,19 @@
               :loading="exportLoading"
               @click="handleExport"
               v-hasPermi="['system:user:export']"
-            >导出</el-button>
+            >{{$t('bt.export')}}</el-button>
           </el-col>
           <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
         </el-row>
 
         <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
           <el-table-column type="selection" width="50" align="center" />
-          <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
-          <el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
-          <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
-          <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
-          <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
-          <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
+          <el-table-column :label="$t('system.user.userId')" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
+          <el-table-column :label="$t('system.user.userName')" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
+          <el-table-column :label="$t('system.user.nickName')" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
+          <el-table-column :label="$t('system.user.deptName')" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
+          <el-table-column :label="$t('system.user.phonenumber')" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
+          <el-table-column :label="$t('system.user.status')" align="center" key="status" v-if="columns[5].visible">
             <template slot-scope="scope">
               <el-switch
                 v-model="scope.row.status"
@@ -156,13 +156,13 @@
               ></el-switch>
             </template>
           </el-table-column>
-          <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
+          <el-table-column :label="$t('system.user.createTime')" align="center" prop="createTime" v-if="columns[6].visible" width="160">
             <template slot-scope="scope">
               <span>{{ parseTime(scope.row.createTime) }}</span>
             </template>
           </el-table-column>
           <el-table-column
-            label="操作"
+            :label="$t('hint.operate')"
             align="center"
             width="160"
             class-name="small-padding fixed-width"
@@ -174,23 +174,23 @@
                 icon="el-icon-edit"
                 @click="handleUpdate(scope.row)"
                 v-hasPermi="['system:user:edit']"
-              >修改</el-button>
+              >{{$t('bt.edit')}}</el-button>
               <el-button
                 size="mini"
                 type="text"
                 icon="el-icon-delete"
                 @click="handleDelete(scope.row)"
                 v-hasPermi="['system:user:remove']"
-              >删除</el-button>
+              >{{$t('bt.delete')}}</el-button>
               <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
                 <span class="el-dropdown-link">
-                  <i class="el-icon-d-arrow-right el-icon--right"></i>更多
+                  <i class="el-icon-d-arrow-right el-icon--right"></i>{{$t('bt.more')}}
                 </span>
                 <el-dropdown-menu slot="dropdown">
                   <el-dropdown-item command="handleResetPwd" icon="el-icon-key"
-                    v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
+                    v-hasPermi="['system:user:resetPwd']">{{$t('bt.resetPassWord')}}</el-dropdown-item>
                   <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
-                    v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
+                    v-hasPermi="['system:user:edit']">{{$t('bt.assigningRoles')}}</el-dropdown-item>
                 </el-dropdown-menu>
               </el-dropdown>
             </template>