程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 快速入门

  • 后端手册

    • 分页实现
    • 导入导出功能
    • 文件上传与下载
    • 权限注解实现
    • 事务管理详解
    • 全局异常处理
    • 参数验证详解
    • 数据脱敏详解
    • 系统日志功能实现
    • 数据权限控制
    • 多数据源实现
    • 代码生成功能
    • 定时任务实现
    • 系统接口文档生成
    • 防重复提交实现
    • 国际化支持
      • 一、后台国际化流程
        • 1. 在 SysLoginController.java 中新增语言切换方法
        • 2. 在 SecurityConfig.java 中允许匿名访问语言切换方法
      • 二、前端国际化流程
        • 1. 安装 vue-i18n 依赖
        • 2. 创建国际化文件
        • 3. 在 main.js 中引入并配置 i18n
        • 4. 在 Vuex 中添加语言状态管理
        • 5. 创建语言切换组件
        • 6. 修改登录页面以支持国际化
        • 7. 接口调用中的国际化支持
      • 三、总结
    • 新建子模块
  • 前端手册

  • 组件文档

  • 数据库分析

  • 若依框架
  • 后端手册
scholar
2024-08-31
目录

国际化支持

# 国际化支持

在现代Web应用中,国际化(i18n)支持是非常重要的,尤其是当应用需要面向多个国家或地区的用户时。通过国际化支持,可以根据用户的语言偏好显示相应的文本内容。本文将详细介绍如何在若依框架中实现国际化支持,包括后台和前端的配置步骤。

# 一、后台国际化流程

首先,需要在后端提供一个接口,用于切换语言并保存用户的语言选择。

# 1. 在 SysLoginController.java 中新增语言切换方法

import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 系统登录控制器
 */
@RestController
public class SysLoginController {

    /**
     * 切换语言
     *
     * @param lang 语言代码(如 "zh_CN" 或 "en_US")
     * @return 操作结果
     */
    @GetMapping("/changeLanguage")
    public AjaxResult changeLanguage(String lang) {
        // 在此处可以添加保存用户语言偏好的逻辑,如存入数据库或会话
        return AjaxResult.success("语言切换成功");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2. 在 SecurityConfig.java 中允许匿名访问语言切换方法

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/changeLanguage").permitAll()  // 允许匿名访问
            .anyRequest().authenticated();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 二、前端国际化流程

前端的国际化支持主要通过 vue-i18n 插件实现。

# 1. 安装 vue-i18n 依赖

在项目的 package.json 中的 dependencies 节点添加 vue-i18n,并指定版本号。

"vue-i18n": "7.3.2"
1

然后运行 npm install 进行安装。

# 2. 创建国际化文件

在 src 目录下创建一个 lang 目录,用于存放国际化相关的文件。此处我们需要创建三个文件:index.js、zh.js 和 en.js。

  • index.js:用于配置和初始化 vue-i18n。
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 英文语言包
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'; // Element UI 中文语言包
import enLocale from './en';
import zhLocale from './zh';

Vue.use(VueI18n);

const messages = {
  en_US: {
    ...enLocale,
    ...elementEnLocale
  },
  zh_CN: {
    ...zhLocale,
    ...elementZhLocale
  }
};

const i18n = new VueI18n({
  locale: Cookies.get('language') || 'zh_CN', // 从 Cookie 中获取语言设置
  messages
});

export default i18n;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  • zh.js:存放中文翻译内容。
export default {
  login: {
    title: '若依后台管理系统',
    logIn: '登录',
    username: '账号',
    password: '密码',
    code: '验证码',
    rememberMe: '记住密码'
  },
  tagsView: {
    refresh: '刷新',
    close: '关闭',
    closeOthers: '关闭其它',
    closeAll: '关闭所有'
  },
  settings: {
    title: '系统布局配置',
    theme: '主题色',
    tagsView: '开启 Tags-View',
    fixedHeader: '固定 Header',
    sidebarLogo: '侧边栏 Logo'
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • en.js:存放英文翻译内容。
export default {
  login: {
    title: 'RuoYi Login Form',
    logIn: 'Login in',
    username: 'Username',
    password: 'Password',
    code: 'Code',
    rememberMe: 'Remember Me'
  },
  tagsView: {
    refresh: 'Refresh',
    close: 'Close',
    closeOthers: 'Close Others',
    closeAll: 'Close All'
  },
  settings: {
    title: 'Page style setting',
    theme: 'Theme Color',
    tagsView: 'Open Tags-View',
    fixedHeader: 'Fixed Header',
    sidebarLogo: 'Sidebar Logo'
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 3. 在 main.js 中引入并配置 i18n

在 src/main.js 中引入 i18n,并将其添加到 Vue 实例中。

import Vue from 'vue';
import Element from 'element-ui';
import i18n from './lang'; // 引入国际化配置

Vue.use(Element, {
  i18n: (key, value) => i18n.t(key, value),
  size: Cookies.get('size') || 'medium'
});

Vue.config.productionTip = false;

new Vue({
  el: '#app',
  router,
  store,
  i18n,  // 将 i18n 注入 Vue 实例
  render: h => h(App)
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 4. 在 Vuex 中添加语言状态管理

在 src/store/modules/app.js 中管理语言状态,通过 Vuex 存储和更新语言设置。

import Cookies from 'js-cookie';

const state = {
  language: Cookies.get('language') || 'en_US'
};

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

const actions = {
  setLanguage({ commit }, language) {
    commit('SET_LANGUAGE', language);
  }
};

export default {
  namespaced: true,
  state,
  mutations,
  actions
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 5. 创建语言切换组件

在 src/components/LangSelect/index.vue 中创建语言切换组件。

<template>
  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
    <div>
      <svg-icon class-name="international-icon" icon-class="language" />
    </div>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item :disabled="language==='zh_CN'" command="zh_CN">中文</el-dropdown-item>
      <el-dropdown-item :disabled="language==='en_US'" command="en_US">English</el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</template>

<script>
import { changeLanguage } from "@/api/login";

export default {
  computed: {
    language() {
      return this.$store.getters.language;
    }
  },
  methods: {
    handleSetLanguage(value) {
      this.$i18n.locale = value;
      this.$store.dispatch('app/setLanguage', value);
      this.$message({ message: '设置语言成功', type: 'success' });
      changeLanguage(value).then(() => {
        window.location.reload();
      });
    }
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 6. 修改登录页面以支持国际化

在 src/views/login/index.vue 中使用国际化文本。

<template>
  <div class="login">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
      <h3 class="title">{{ $t('login.title') }}</h3>
      <lang-select class="set-language" />
      <el-form-item prop="username">
        <el-input
          v-model="loginForm.username"
          type="text"
          auto-complete="off"
          :placeholder="$t('login.username')"
        >
          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          auto-complete="off"
          :placeholder="$t('login.password')"
          @keyup.enter.native="handleLogin"
        >
          <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="captchaEnabled">
        <el-input
          v-model="loginForm.code"
          auto-complete="off"
          :placeholder="$t('login.code')"
          style="width: 63%"
          @keyup.enter.native="handleLogin"
        >
          <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"/>
        </div>
      </el-form-item>
      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px

;">{{ $t('login.rememberMe') }}</el-checkbox>
      <el-form-item style="width:100%;">
        <el-button
          :loading="loading"
          size="medium"
          type="primary"
          style="width:100%;"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">{{ $t('login.logIn') }}</span>
          <span v-else>登 录 中...</span>
        </el-button>
        <div style="float: right;" v-if="register">
          <router-link class="link-type" :to="'/register'">立即注册</router-link>
        </div>
      </el-form-item>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
    </div>
  </div>
</template>

<script>
import LangSelect from '@/components/LangSelect'
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from '@/utils/jsencrypt'

export default {
  name: "Login",
  components: { LangSelect },
  data() {
    return {
      codeUrl: "",
      loginForm: {
        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: "请输入验证码" }]
      },
      loading: false,
      captchaEnabled: true,
      register: false,
      redirect: undefined
    };
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true
    }
  },
  created() {
    this.getCode();
    this.getCookie();
  },
  methods: {
    getCode() {
      getCodeImg().then(res => {
        this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
        if (this.captchaEnabled) {
          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 rememberMe = Cookies.get('rememberMe')
      this.loginForm = {
        username: username === undefined ? this.loginForm.username : username,
        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;
          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 });
          } else {
            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.captchaEnabled) {
              this.getCode();
            }
          });
        }
      });
    }
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

# 7. 接口调用中的国际化支持

在 src/api/login.js 中新增语言切换方法,供前端组件调用。

import request from '@/utils/request'

// 修改语言
export function changeLanguage(lang) {
  return request({
    url: '/changeLanguage',
    method: 'get',
    headers: {
      isToken: false,
    },
    params: {
      lang: lang
    }
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 三、总结

通过上述步骤,我们可以轻松地为若依框架的前后端分离项目添加国际化支持。前端使用 vue-i18n 插件结合 Vuex 管理语言状态,并在需要国际化支持的组件中使用翻译函数 $t 进行文本渲染。后端提供了一个简单的接口,用于切换用户的语言偏好。

  • 灵活性:支持动态切换语言,用户可以根据需求选择适合自己的语言环境。
  • 易于扩展:可以轻松地添加更多语言支持,只需在前端的 lang 目录中添加相应的语言文件即可。
  • 集成性:与 Element UI 组件库紧密集成,国际化配置可统一管理,避免了多处重复配置的问题。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
防重复提交实现
新建子模块

← 防重复提交实现 新建子模块→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式