diff --git a/package-lock.json b/package-lock.json index 5c32dacbeb844c99573a570ad8dff0f98100274a..0b8b43517373b88249bbc5cdf1a00ffb3e4f60e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "nprogress": "^0.2.0", "vditor": "^3.8.5", "vue": "^2.6.11", + "vue-i18n": "^8.24.4", "vue-router": "^3.5.1", "vuex": "^3.6.2" }, @@ -11889,6 +11890,11 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "node_modules/vue-i18n": { + "version": "8.24.4", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.24.4.tgz", + "integrity": "sha512-RZE94WUAGxEiBAANxQ0pptbRwDkNKNSXl3fnJslpFOxVMF6UkUtMDSuYGuW2blDrVgweIXVpethOVkYoNNT9xw==" + }, "node_modules/vue-loader": { "version": "15.9.7", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz", @@ -23146,6 +23152,11 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "vue-i18n": { + "version": "8.24.4", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.24.4.tgz", + "integrity": "sha512-RZE94WUAGxEiBAANxQ0pptbRwDkNKNSXl3fnJslpFOxVMF6UkUtMDSuYGuW2blDrVgweIXVpethOVkYoNNT9xw==" + }, "vue-loader": { "version": "15.9.7", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz", diff --git a/package.json b/package.json index febe6fd9c90d853ce5f7eb7d8967787a25c3c253..b36761cae8a1b512fcd7b553409184234d7dda91 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "nprogress": "^0.2.0", "vditor": "^3.8.5", "vue": "^2.6.11", + "vue-i18n": "^8.24.4", "vue-router": "^3.5.1", "vuex": "^3.6.2" }, diff --git a/src/App.vue b/src/App.vue index c53fd6454a08863cacfce6a327a5915bb24be3ce..7965654c1afc72d3ec8deab14a9745a39bc34ccb 100644 --- a/src/App.vue +++ b/src/App.vue @@ -18,10 +18,15 @@ diff --git a/src/component/BackTop.vue b/src/component/BackTop.vue index a08dded361178e8c1e491f448d25c4bb28c358f4..758b964f28a4dc7c86202c665e24892d1b3f2ba7 100644 --- a/src/component/BackTop.vue +++ b/src/component/BackTop.vue @@ -1,7 +1,7 @@ @@ -32,8 +32,9 @@ 检索 + >{{ $t('Header.search') }}

@@ -55,7 +56,7 @@ passive-type="is-warning" type="is-dark" > - {{ darkMode ? "夜" : "日" }} + {{ darkMode ? $t('Header.night') : $t('Header.day') }} @@ -69,14 +70,14 @@ tag="router-link" :to="{ path: '/register' }" > - 注册 + {{ $t('Header.signUp') }} - 登录 + {{ $t('Header.signIn') }} @@ -89,20 +90,20 @@ tag="router-link" :to="{ path: `/member/${user.username}/home` }" > - 🧘 个人中心 + 🧘 {{ $t('Header.personalCenter') }} - ⚙ 设置中心 + ⚙ {{ $t('Header.settings') }} 👋 退出登录 + > 👋 {{ $t('Header.signOut') }} @@ -150,7 +151,7 @@ export default { methods: { async logout() { this.$store.dispatch('user/logout').then(() => { - this.$message.info('退出登录成功!') + this.$message.info(this.$t('Header.successOut')) setTimeout(() => { this.$router.push({ path: this.redirect || '/' }) }, 500) @@ -161,7 +162,7 @@ export default { if (this.searchKey.trim() === null || this.searchKey.trim() === '') { this.$message.info({ showClose: true, - message: '请输入关键字搜索!', + message: this.$t('Header.blankSearch'), type: 'warning' }) return false diff --git a/src/i18n/index.js b/src/i18n/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2f6e7682a9715de1ff4ed4203873a2f663e2e7ad --- /dev/null +++ b/src/i18n/index.js @@ -0,0 +1,10 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +Vue.use(VueI18n) + +import messages from './lang' +export default new VueI18n({ + locale: 'zh', + messages +}) \ No newline at end of file diff --git a/src/i18n/lang/en.js b/src/i18n/lang/en.js new file mode 100644 index 0000000000000000000000000000000000000000..d47be11ea6ac8127f9d30a6c7c0357fa0645d147 --- /dev/null +++ b/src/i18n/lang/en.js @@ -0,0 +1,112 @@ +export default { + Header: { + homePage: 'Home', + searchHint: 'Search for post, tag or user', + search: 'Search', + day: 'Day', + night: 'Night', + signUp: 'Sign up', + signIn: 'Sign in', + personalCenter: 'Profile', + settings: 'Settings', + signOut: 'Sign out', + successOut: 'Successfully sign out!', + blankSearch: 'Please enter a keyword!' + }, + Footer: { + slogan: 'An intelligent community system for XD people', + admin: 'Admin' + }, + BackTop: { + title: 'Back to the top' + }, + Login: { + signIn: 'Sign in', + account: 'Username', + password: 'Password', + remember: 'Remember', + reset: 'Reset', + blankAccount: 'Please enter your account', + errAccount: 'The length should be 2-15 characters', + blankPassword: 'Please enter your password', + errPassword: 'The length should be 6-20 characters', + successIn: 'Congratulations! Login successfully' + }, + Register: { + newOne: 'New Account', + account: 'Username', + password: 'Password', + password2: 'Confirm password', + email: 'Email', + signUp: 'Sign up', + reset: 'Reset', + rePass: 'Please enter your password again', + matchPass: 'Two input password does not match!', + blankAccount: 'Please enter your account', + errAccount: 'The length should be 2-15 characters', + blankPassword: 'Please enter your password', + errPassword: 'The length should be 6-20 characters', + checkPassword: 'Please enter your password again', + blankEmail: 'Please enter your email address', + errEmail: 'Please enter the correct email address', + successUp: 'Account registration successful!', + failUp: 'Registration failed' + }, + card: { + post: 'Post', + posting: 'Publish idea', + settled: 'Sign up', + signIn: 'Sign in', + promotion: 'Promotion', + detail: 'Not received related promotion!', + sentence: 'Daily sentence' + }, + post: { + author: 'Author', + theme: 'Theme / Release theme', + theme2: 'Theme / Update theme', + enterTopic: 'Enter the topic', + enterTopic2: 'Enter the new topic', + enterTag: 'Please enter tags, limited to 15 characters and 3 tags', + post: 'Post', + reset: 'Reset', + blankTopic: 'Please enter the topic', + errTopic: 'The length should be 1-15 characters', + enterContent: 'Enter content here...', + hintContent: 'Content cannot be empty', + hintTag: 'Tags cannot be empty', + views: 'Views', + edit: 'Edit', + del: 'Delete', + update: 'Update', + latest: 'Latest topics', + release: 'Released', + view: 'Views', + hot: 'Hot Topics' + }, + user: { + score: 'Score', + join: 'Join', + bio: 'Bio', + topics: 'Topics', + blankTopic: 'No topic', + settings: 'Settings', + info: 'Basic Info', + account: 'Username', + name: 'Nickname', + avatar: 'Avatar', + submit: 'Submit', + email: 'Email', + blankEmail: 'Please enter your email address', + errEmail: 'Please enter the correct email address', + phone: 'Phone', + success: 'Profile updated' + }, + comment: { + title: 'Comment', + placeholder: 'Add a comment...', + submit: 'Submit', + success: 'Comment successfully', + failed: 'Cannot comment to this post, {0}' + } +} \ No newline at end of file diff --git a/src/i18n/lang/index.js b/src/i18n/lang/index.js new file mode 100644 index 0000000000000000000000000000000000000000..05674323ddd6d1d40eb55b11d7f3b6260c33c580 --- /dev/null +++ b/src/i18n/lang/index.js @@ -0,0 +1,7 @@ +import zh from './zh' +import en from './en' + +export default { + zh, + en +} \ No newline at end of file diff --git a/src/i18n/lang/zh.js b/src/i18n/lang/zh.js new file mode 100644 index 0000000000000000000000000000000000000000..a9ae105a18a2326a90c5952fa9f0494bbe519ea5 --- /dev/null +++ b/src/i18n/lang/zh.js @@ -0,0 +1,112 @@ +export default { + Header: { + homePage: '主页', + searchHint: '搜索帖子、标签和用户', + search: '检索', + day: '日', + night: '夜', + signUp: '注册', + signIn: '登录', + personalCenter: '个人中心', + settings: '设置中心', + signOut: '退出登录', + successOut: '退出登录成功!', + blankSearch: '请输入关键字搜索!' + }, + Footer: { + slogan: '只属于西电人的智慧社区系统', + admin: '管理员登录' + }, + BackTop: { + title: '回到顶部' + }, + Login: { + signIn: '登录', + account: '账号', + password: '密码', + remember: '记住', + reset: '重置', + blankAccount: '请输入账号', + errAccount: '长度在2-15字符', + blankPassword: '请输入密码', + errPassword: '长度在6到20个字符', + successIn: '恭喜你,登录成功' + }, + Register: { + newOne: '新用户入驻', + account: '账号', + password: '密码', + password2: '确认密码', + email: '邮箱', + signUp: '立即注册', + reset: '重置', + rePass: '请再次输入密码', + matchPass: '两次输入密码不一致!', + blankAccount: '请输入账号', + errAccount: '长度在2-15字符', + blankPassword: '请输入密码', + errPassword: '长度在6到20个字符', + checkPassword: '请重新输入密码', + blankEmail: '请输入邮箱', + errEmail: '请输入正确邮箱', + successUp: '账号注册成功!', + failUp: '注册失败' + }, + card: { + post: '发帖', + posting: '发表想法', + settled: '马上入驻', + signIn: '社区登入', + promotion: '推广', + detail: '未收到有关推广!', + sentence: '每日一句' + }, + post: { + author: '作者', + theme: '主题 / 发布主题', + theme2: '主题 / 更新主题', + enterTopic: '输入主题名称', + enterTopic2: '输入新的主题名称', + enterTag: '请输入主题标签,限制为15个字符和3个标签', + post: '发表帖子', + reset: '重置', + blankTopic: '请输入话题名称', + errTopic: '长度在1到25个字符之间', + enterContent: '此处输入内容...', + hintContent: '话题内容不能为空', + hintTag: '标签不能为空', + views: '查看', + edit: '编辑', + del: '删除', + update: '更新', + latest: '最新主题', + release: '发布于', + view: '浏览', + hot: '热门主题' + }, + user: { + score: '积分', + join: '入驻', + bio: '简介', + topics: '话题', + blankTopic: '暂无话题', + settings: '个人设置', + info: '基础信息', + account: '账号', + name: '昵称', + avatar: '头像', + submit: '提交', + email: '电子邮箱', + blankEmail: '请输入邮箱地址', + errEmail: '请输入正确的邮箱地址', + phone: '手机号', + success: '信息修改成功' + }, + comment: { + title: '评论', + placeholder: '此处输入评论...', + submit: '提交', + success: '评论成功', + failed: '无法在此帖发表评论, {0}' + } +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index ed6d55b16539d09835c3a8dd598d81c57713428f..3e242ff30d144e3979dd41e582cbe962a854794b 100644 --- a/src/main.js +++ b/src/main.js @@ -16,6 +16,7 @@ import '@/permission' import relativeTime from 'dayjs/plugin/relativeTime' import 'dayjs/locale/zh-cn' +import i18n from './i18n' const dayjs = require('dayjs'); dayjs.extend(relativeTime) @@ -37,6 +38,7 @@ Vue.config.productionTip = false new Vue({ router, store, + i18n, render: h => h(App), }).$mount('#app') diff --git a/src/router/index.js b/src/router/index.js index e4877382fdd1c4668ad48ffda07742acb50d3e95..52c5cb26870bda6a6cdc65bfca254ac416394651 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,5 +1,6 @@ import Vue from "vue"; import VueRouter from "vue-router"; +import { getLang } from "@/util/auth"; Vue.use(VueRouter); @@ -14,7 +15,7 @@ const routes = [{ component: () => import('@/view/auth/Register'), meta: { - title: "注册" + title: getLang() === 'zh' ? "注册" : 'Sign up' } }, { @@ -32,7 +33,7 @@ const routes = [{ component: () => import('@/view/auth/Login'), meta: { - title: "登录" + title: getLang() === 'zh' ? "登录" : 'Sign in' } }, { @@ -40,7 +41,7 @@ const routes = [{ name: 'post-create', component: () => import('@/view/post/Create'), meta: { - title: '发布帖子', + title: getLang() === 'zh' ? '发布帖子' : 'Create Post', requireAuth: true } }, @@ -54,7 +55,7 @@ const routes = [{ path: '/post/edit/:id', component: () => import('@/view/post/Edit'), meta: { - title: '编辑帖子', + title: getLang() === 'zh' ? '编辑帖子' : 'Edit post', requireAuth: true } }, @@ -69,7 +70,7 @@ const routes = [{ name: 'user', component: () => import('@/view/user/Profile'), meta: { - title: '用户主页' + title: getLang() === 'zh' ? '用户主页' : 'Profile' } }, //用户设置 @@ -79,7 +80,7 @@ const routes = [{ name: 'user-setting', component: () => import('@/view/user/Setting'), meta: { - title: '设置' + title: getLang() === 'zh' ? '设置' : 'Settings' } } ] diff --git a/src/util/auth.js b/src/util/auth.js index bedb03179f3af2ee68aed5b0d616d73207f4b498..9cdcf432d5892e829f817f9f1f2e3e693e14326c 100644 --- a/src/util/auth.js +++ b/src/util/auth.js @@ -1,7 +1,7 @@ import Cookies from 'js-cookie' const uToken = 'u_token' -const darkMode = 'dark_mode'; +const darkMode = 'dark_mode' // 获取Token export function getToken() { @@ -28,4 +28,12 @@ export function setDarkMode(mode) { export function getDarkMode() { return !(undefined === Cookies.get(darkMode) || 'false' === Cookies.get(darkMode)); +} + +export function setLang(lang) { + return Cookies.set('language', lang, {expires: 365}) +} + +export function getLang() { + return ('undefined' === Cookies.get('language')) ? 'zh' : Cookies.get('language') } \ No newline at end of file diff --git a/src/util/get-page-title.js b/src/util/get-page-title.js index b2463e9d1b0a01703e87614357f6ac7e4bd21ad3..5bebfdeb39878e9e67f3ada576c09ce642727fc4 100644 --- a/src/util/get-page-title.js +++ b/src/util/get-page-title.js @@ -1,4 +1,5 @@ -const title = "长安南论坛——西电智慧论坛" +import { getLang } from "@/util/auth" +const title = getLang() === 'zh' ? '长安南论坛——西电智慧论坛' : 'Chang\'an Nan Forum——XD Smart Forum' export default function getPageTitle(pageTitle){ if(pageTitle){ diff --git a/src/view/auth/Login.vue b/src/view/auth/Login.vue index bcebc235018bcb1517fa89ffcc9d313ed9267113..89acbf448eae1e905743d5dcc4f34cb523a73d22 100644 --- a/src/view/auth/Login.vue +++ b/src/view/auth/Login.vue @@ -3,7 +3,7 @@
- 登录 + {{ $t('Login.signIn') }}
- + - + - + - 登录 + {{ $t('Login.signIn') }} - 重置 + {{ $t('Login.reset') }} @@ -57,20 +57,20 @@ export default { }, rules: { name: [ - { required: true, message: "请输入账号", trigger: "blur" }, + { required: true, message: this.$t('Login.blankAccount'), trigger: "blur" }, { min: 2, max: 15, - message: "长度在2-15字符", - trigger: blur, + message: this.$t('Login.errAccount'), + trigger: "blur", }, ], password: [ - { required: true, message: "请输入密码", trigger: "blur" }, + { required: true, message: this.$t('Login.blankPassword'), trigger: "blur" }, { min: 6, max: 20, - message: "长度在6到20个字符", + message: this.$t('Login.errPassword'), trigger: "blur", }, ], @@ -87,7 +87,7 @@ export default { .dispatch("user/login", this.ruleForm) .then(() => { this.$message({ - message: "恭喜你,登录成功", + message: this.$t('Login.successIn'), type: "success", duration: 2000, }); diff --git a/src/view/auth/Register.vue b/src/view/auth/Register.vue index a0c3716521b7d94b305f096c9a79d66e175c7dec..abaede62f9352042b37c40a2ee80c55df0cf1ae4 100644 --- a/src/view/auth/Register.vue +++ b/src/view/auth/Register.vue @@ -3,7 +3,7 @@
- 新用户入驻 + {{ $t('Register.newOne') }}
- + - + - + - + - 立即注册 + {{ $t('Register.signUp') }} - 重置 + {{ $t('Register.reset') }} @@ -61,9 +61,9 @@ export default { data() { const validatePass = (rule, value, callback) => { if (value == "") { - callback(new Error("请再次输入密码")); + callback(new Error(this.$t('Register.rePass'))); } else if (value != this.ruleForm.password) { - callback(new Error("两次输入密码不一致!")); + callback(new Error(this.$t('Register.matchPass'))); } else { callback(); } @@ -78,36 +78,36 @@ export default { }, rules: { name: [ - { required: true, message: "请输入账号", trigger: "blur" }, + { required: true, message: this.$t('Register.blankAccount'), trigger: "blur" }, { min: 2, max: 10, - message: "长度在2-15字符", - trigger: blur, + message: this.$t('Register.errAccount'), + trigger: "blur", }, ], password: [ - { required: true, message: "请输入密码", trigger: "blur" }, + { required: true, message: this.$t('Register.blankPassword'), trigger: "blur" }, { min: 6, max: 20, - message: "长度在6到20个字符", + message: this.$t('Register.errPassword'), trigger: "blur", }, ], checkPassword: [ - { required: true, message: "请重新输入密码", trigger: "blur" }, + { required: true, message: this.$t('Register.checkPassword'), trigger: "blur" }, { validator: validatePass, trigger: "blur", }, ], email: [ - { required: true, message: "请输入邮箱", trigger: "blur" }, + { required: true, message: this.$t('Register.blankEmail'), trigger: "blur" }, { type: "email", - message: "请输入正确邮箱", - trigger: ["blur ", "change"], + message: this.$t('Register.errEmail'), + trigger: ["blur", "change"], }, ], }, @@ -124,7 +124,7 @@ export default { const { code, message } = value; if (code === 200) { this.$message({ - message: "账号注册成功!", + message: this.$t('Register.successUp'), type: "success", }); setTimeout(() => { @@ -132,7 +132,7 @@ export default { this.$router.push({ path: this.redirect || "/login" }); }, 0.1 * 1000); } else { - this.$message.error("注册失败" + message); + this.$message.error(this.$t('Register.failUp') + message); } }) .catch(() => { @@ -151,4 +151,7 @@ export default { \ No newline at end of file diff --git a/src/view/card/LoginWelcome.vue b/src/view/card/LoginWelcome.vue index fc55741c67dc76f5340f0166c6e00235a87e615f..f373dddca4d1299de6c13981eb4d064a8c2d0346 100644 --- a/src/view/card/LoginWelcome.vue +++ b/src/view/card/LoginWelcome.vue @@ -1,15 +1,15 @@ diff --git a/src/view/card/Promotion.vue b/src/view/card/Promotion.vue index 6d58c03e25fb29df3f76b80d92f97532d32e311e..a9e20d1a18c0c01e63af037080bf74031755fb2f 100644 --- a/src/view/card/Promotion.vue +++ b/src/view/card/Promotion.vue @@ -1,10 +1,10 @@ @@ -16,9 +16,6 @@ export default { data() { return { } - }, - created() { - }, methods: { diff --git a/src/view/card/Tip.vue b/src/view/card/Tip.vue index 25a7204a4811d5138b0875316b8bf70ae878a7c0..b549854b27bd07d84a433c1fefdd58449f26b4a3 100644 --- a/src/view/card/Tip.vue +++ b/src/view/card/Tip.vue @@ -1,7 +1,7 @@