Commit 90d0b6a4605535068aa0443db0f756bb606e0b49
1 parent
f929fef0
feat(i18n) setup i18n config
Showing
11 changed files
with
208 additions
and
3 deletions
front-end/h5/package.json
| @@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
| 23 | "register-service-worker": "^1.6.2", | 23 | "register-service-worker": "^1.6.2", |
| 24 | "strapi-sdk-javascript": "^0.3.1", | 24 | "strapi-sdk-javascript": "^0.3.1", |
| 25 | "vue": "^2.6.10", | 25 | "vue": "^2.6.10", |
| 26 | + "vue-i18n": "^8.14.1", | ||
| 26 | "vue-router": "^3.0.3", | 27 | "vue-router": "^3.0.3", |
| 27 | "vuex": "^3.0.1" | 28 | "vuex": "^3.0.1" |
| 28 | }, | 29 | }, |
front-end/h5/src/components/common/header/LangSelect.vue
0 → 100755
| 1 | +<template> | ||
| 2 | + <a-dropdown> | ||
| 3 | + <span class="action global-lang"> | ||
| 4 | + <!-- <a-icon type="global" style="font-size: 16px"/> --> | ||
| 5 | + {{langFlag}} | ||
| 6 | + </span> | ||
| 7 | + <a-menu slot="overlay" style="width: 150px;" @click="SwitchLang"> | ||
| 8 | + <a-menu-item key="zh-CN"> | ||
| 9 | + <a rel="noopener noreferrer"> | ||
| 10 | + <span role="img" aria-label="简体中文">🇨🇳</span> 简体中文 | ||
| 11 | + </a> | ||
| 12 | + </a-menu-item> | ||
| 13 | + <a-menu-item key="en-US"> | ||
| 14 | + <a rel="noopener noreferrer"> | ||
| 15 | + <span role="img" aria-label="English">🇺🇸</span> English | ||
| 16 | + </a> | ||
| 17 | + </a-menu-item> | ||
| 18 | + </a-menu> | ||
| 19 | + </a-dropdown> | ||
| 20 | +</template> | ||
| 21 | + | ||
| 22 | +<script> | ||
| 23 | +import langMixin from '@/mixins/i18n' | ||
| 24 | + | ||
| 25 | +export default { | ||
| 26 | + name: 'LangSelect', | ||
| 27 | + mixins: [langMixin], | ||
| 28 | + computed: { | ||
| 29 | + langFlag () { | ||
| 30 | + switch (this.currentLang) { | ||
| 31 | + case 'zh-CN': | ||
| 32 | + return '🇨🇳' | ||
| 33 | + case 'en-US': | ||
| 34 | + return '🇺🇸' | ||
| 35 | + default: | ||
| 36 | + return '🇨🇳' | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + }, | ||
| 40 | + methods: { | ||
| 41 | + SwitchLang (row) { | ||
| 42 | + this.setLang(row.key) | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | +} | ||
| 46 | +</script> |
front-end/h5/src/components/core/editor/index.js
| @@ -16,6 +16,7 @@ import PreviewDialog from './modals/preview.vue' | @@ -16,6 +16,7 @@ import PreviewDialog from './modals/preview.vue' | ||
| 16 | 16 | ||
| 17 | import LogoOfHeader from '@/components/common/header/logo.js' | 17 | import LogoOfHeader from '@/components/common/header/logo.js' |
| 18 | import ExternalLinksOfHeader from '@/components/common/header/links.js' | 18 | import ExternalLinksOfHeader from '@/components/common/header/links.js' |
| 19 | +import LangSelect from '@/components/common/header/LangSelect.vue' | ||
| 19 | 20 | ||
| 20 | const sidebarMenus = [ | 21 | const sidebarMenus = [ |
| 21 | { | 22 | { |
| @@ -85,7 +86,8 @@ export default { | @@ -85,7 +86,8 @@ export default { | ||
| 85 | name: 'Editor', | 86 | name: 'Editor', |
| 86 | components: { | 87 | components: { |
| 87 | LogoOfHeader, | 88 | LogoOfHeader, |
| 88 | - ExternalLinksOfHeader | 89 | + ExternalLinksOfHeader, |
| 90 | + LangSelect | ||
| 89 | }, | 91 | }, |
| 90 | data: () => ({ | 92 | data: () => ({ |
| 91 | activeMenuKey: 'pluginList', | 93 | activeMenuKey: 'pluginList', |
| @@ -195,6 +197,7 @@ export default { | @@ -195,6 +197,7 @@ export default { | ||
| 195 | </a-menu-item> | 197 | </a-menu-item> |
| 196 | </a-menu> | 198 | </a-menu> |
| 197 | <ExternalLinksOfHeader /> | 199 | <ExternalLinksOfHeader /> |
| 200 | + <LangSelect /> | ||
| 198 | </a-layout-header> | 201 | </a-layout-header> |
| 199 | <a-layout> | 202 | <a-layout> |
| 200 | <a-layout-sider width="160" style="background: #fff" collapsed> | 203 | <a-layout-sider width="160" style="background: #fff" collapsed> |
| @@ -217,7 +220,7 @@ export default { | @@ -217,7 +220,7 @@ export default { | ||
| 217 | <a-layout-sider width="240" theme='light' style={{ background: '#fff', padding: '12px' }}> | 220 | <a-layout-sider width="240" theme='light' style={{ background: '#fff', padding: '12px' }}> |
| 218 | { this._renderMenuContent() } | 221 | { this._renderMenuContent() } |
| 219 | </a-layout-sider> | 222 | </a-layout-sider> |
| 220 | - <a-layout style="padding: 0 24px 24px"> | 223 | + <a-layout style="padding: 0 0 24px"> |
| 221 | <a-layout-content style={{ padding: '24px', margin: 0, minHeight: '280px' }}> | 224 | <a-layout-content style={{ padding: '24px', margin: 0, minHeight: '280px' }}> |
| 222 | <div style="text-align: center;"> | 225 | <div style="text-align: center;"> |
| 223 | <a-radio-group | 226 | <a-radio-group |
front-end/h5/src/locales/index.js
0 → 100755
| 1 | +import Vue from 'vue' | ||
| 2 | +import VueI18n from 'vue-i18n' | ||
| 3 | +// default language | ||
| 4 | +import enUSLang from './lang/en-US' | ||
| 5 | +import zhCNLang from './lang/zh-CN' | ||
| 6 | + | ||
| 7 | +Vue.use(VueI18n) | ||
| 8 | + | ||
| 9 | +const messages = { | ||
| 10 | + 'en-US': { | ||
| 11 | + ...enUSLang | ||
| 12 | + }, | ||
| 13 | + 'zh-CN': { | ||
| 14 | + ...zhCNLang | ||
| 15 | + } | ||
| 16 | +} | ||
| 17 | +export const defaultLang = 'zh-CN' | ||
| 18 | + | ||
| 19 | +const i18n = new VueI18n({ | ||
| 20 | + locale: defaultLang, | ||
| 21 | + fallbackLocale: defaultLang, | ||
| 22 | + messages | ||
| 23 | +}) | ||
| 24 | + | ||
| 25 | +export default i18n | ||
| 26 | + | ||
| 27 | +const loadedLanguages = [defaultLang] | ||
| 28 | + | ||
| 29 | +function setI18nLanguage (lang) { | ||
| 30 | + i18n.locale = lang | ||
| 31 | + document.querySelector('html').setAttribute('lang', lang) | ||
| 32 | + return lang | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +export function loadLanguageAsync (lang = defaultLang) { | ||
| 36 | + return new Promise(resolve => { | ||
| 37 | + if (i18n.locale !== lang) { | ||
| 38 | + if (!loadedLanguages.includes(lang)) { | ||
| 39 | + return import(/* webpackChunkName: "lang-[request]" */ `./lang/${lang}`).then(msg => { | ||
| 40 | + i18n.setLocaleMessage(lang, msg.default) | ||
| 41 | + loadedLanguages.push(lang) | ||
| 42 | + return setI18nLanguage(lang) | ||
| 43 | + }) | ||
| 44 | + } | ||
| 45 | + return resolve(setI18nLanguage(lang)) | ||
| 46 | + } | ||
| 47 | + return resolve(lang) | ||
| 48 | + }) | ||
| 49 | +} |
front-end/h5/src/locales/lang/en-US.js
0 → 100755
| 1 | +export default { | ||
| 2 | + app: { | ||
| 3 | + title: 'Luban H5' | ||
| 4 | + }, | ||
| 5 | + header: { | ||
| 6 | + chineseDocument: '中文文档', | ||
| 7 | + englishDocument: 'Document(En)', | ||
| 8 | + chat: 'Discussion Group', // | ||
| 9 | + logout: 'Logout' | ||
| 10 | + }, | ||
| 11 | + sidebar: { | ||
| 12 | + myWorks: 'My Works', | ||
| 13 | + dataCenter: 'Data Center', | ||
| 14 | + basicData: 'Basic Data', | ||
| 15 | + templateCenter: 'Templates', | ||
| 16 | + freeTemplates: 'Templates List', | ||
| 17 | + accountCenter: 'Account' | ||
| 18 | + }, | ||
| 19 | + workCard: { | ||
| 20 | + description: 'Desc', | ||
| 21 | + createTime: 'Time', | ||
| 22 | + useNow: 'Use it Now', | ||
| 23 | + preview: 'Preview', | ||
| 24 | + edit: 'Edit', | ||
| 25 | + createNewWork: 'Create New' | ||
| 26 | + }, | ||
| 27 | + basicData: { | ||
| 28 | + viewData: 'View Data' | ||
| 29 | + } | ||
| 30 | +} |
front-end/h5/src/locales/lang/zh-CN.js
0 → 100755
| 1 | +export default { | ||
| 2 | + header: { | ||
| 3 | + chineseDocument: '中文文档', | ||
| 4 | + englishDocument: '英文文档', | ||
| 5 | + chat: '交流群', // Discussion Group | ||
| 6 | + logout: '退出登录' | ||
| 7 | + }, | ||
| 8 | + sidebar: { | ||
| 9 | + myWorks: '我的作品', | ||
| 10 | + dataCenter: '数据中心', | ||
| 11 | + basicData: '基础数据', | ||
| 12 | + templateCenter: '模板中心', | ||
| 13 | + freeTemplates: '模板列表', | ||
| 14 | + accountCenter: '账号中心' | ||
| 15 | + }, | ||
| 16 | + workCard: { | ||
| 17 | + description: '描述', | ||
| 18 | + createTime: '时间', | ||
| 19 | + useNow: '立即使用', | ||
| 20 | + preview: '预览', | ||
| 21 | + createNewWork: '创建新作品', | ||
| 22 | + edit: '编辑' | ||
| 23 | + }, | ||
| 24 | + basicData: { | ||
| 25 | + viewData: 'View Data' | ||
| 26 | + } | ||
| 27 | +} |
front-end/h5/src/main.js
| @@ -2,6 +2,7 @@ import Vue from 'vue' | @@ -2,6 +2,7 @@ import Vue from 'vue' | ||
| 2 | import App from './App.vue' | 2 | import App from './App.vue' |
| 3 | import router from './router' | 3 | import router from './router' |
| 4 | import store from './store/' | 4 | import store from './store/' |
| 5 | +import i18n from './locales' | ||
| 5 | // import './registerServiceWorker' | 6 | // import './registerServiceWorker' |
| 6 | // import ElementUI from 'element-ui' | 7 | // import ElementUI from 'element-ui' |
| 7 | import Antd from 'ant-design-vue' | 8 | import Antd from 'ant-design-vue' |
| @@ -18,5 +19,6 @@ Vue.use(Antd) | @@ -18,5 +19,6 @@ Vue.use(Antd) | ||
| 18 | new Vue({ | 19 | new Vue({ |
| 19 | router, | 20 | router, |
| 20 | store, | 21 | store, |
| 22 | + i18n, | ||
| 21 | render: h => h(App) | 23 | render: h => h(App) |
| 22 | }).$mount('#app') | 24 | }).$mount('#app') |
front-end/h5/src/mixins/i18n.js
0 → 100755
front-end/h5/src/store/index.js
| @@ -5,6 +5,7 @@ import editor from './modules/editor' | @@ -5,6 +5,7 @@ import editor from './modules/editor' | ||
| 5 | import user from './modules/user' | 5 | import user from './modules/user' |
| 6 | import visible from './modules/visible' | 6 | import visible from './modules/visible' |
| 7 | import loading from './modules/loading' | 7 | import loading from './modules/loading' |
| 8 | +import i18n from './modules/i18n' | ||
| 8 | 9 | ||
| 9 | Vue.use(Vuex) | 10 | Vue.use(Vuex) |
| 10 | 11 | ||
| @@ -22,7 +23,8 @@ export default new Vuex.Store({ | @@ -22,7 +23,8 @@ export default new Vuex.Store({ | ||
| 22 | editor, | 23 | editor, |
| 23 | user, | 24 | user, |
| 24 | visible, | 25 | visible, |
| 25 | - loading | 26 | + loading, |
| 27 | + i18n | ||
| 26 | }, | 28 | }, |
| 27 | plugins: [undoRedoPlugin] | 29 | plugins: [undoRedoPlugin] |
| 28 | }) | 30 | }) |
front-end/h5/src/store/modules/i18n.js
0 → 100755
| 1 | +import { loadLanguageAsync } from '@/locales' | ||
| 2 | + | ||
| 3 | +const i18n = { | ||
| 4 | + namespaced: true, | ||
| 5 | + state: { | ||
| 6 | + lang: 'zh-CN' | ||
| 7 | + }, | ||
| 8 | + mutations: { | ||
| 9 | + SET_LANG: (state, lang) => { | ||
| 10 | + state.lang = lang | ||
| 11 | + } | ||
| 12 | + }, | ||
| 13 | + actions: { | ||
| 14 | + // 设置界面语言 | ||
| 15 | + SetLang ({ commit }, lang) { | ||
| 16 | + return new Promise(resolve => { | ||
| 17 | + commit('SET_LANG', lang) | ||
| 18 | + loadLanguageAsync(lang) | ||
| 19 | + resolve() | ||
| 20 | + }) | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +export default i18n |
front-end/h5/yarn.lock
| @@ -10885,6 +10885,11 @@ vue-hot-reload-api@^2.3.0: | @@ -10885,6 +10885,11 @@ vue-hot-reload-api@^2.3.0: | ||
| 10885 | resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.3.tgz#2756f46cb3258054c5f4723de8ae7e87302a1ccf" | 10885 | resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.3.tgz#2756f46cb3258054c5f4723de8ae7e87302a1ccf" |
| 10886 | integrity sha1-J1b0bLMlgFTF9HI96K5+hzAqHM8= | 10886 | integrity sha1-J1b0bLMlgFTF9HI96K5+hzAqHM8= |
| 10887 | 10887 | ||
| 10888 | +vue-i18n@^8.14.1: | ||
| 10889 | + version "8.14.1" | ||
| 10890 | + resolved "https://registry.npm.taobao.org/vue-i18n/download/vue-i18n-8.14.1.tgz#0ca0a2742c14e0144481655157fffcc7cc313e50" | ||
| 10891 | + integrity sha1-DKCidCwU4BREgWVRV//8x8wxPlA= | ||
| 10892 | + | ||
| 10888 | vue-jest@^3.0.4: | 10893 | vue-jest@^3.0.4: |
| 10889 | version "3.0.4" | 10894 | version "3.0.4" |
| 10890 | resolved "https://registry.npm.taobao.org/vue-jest/download/vue-jest-3.0.4.tgz#b6a2b0d874968f26fa775ac901903fece531e08b" | 10895 | resolved "https://registry.npm.taobao.org/vue-jest/download/vue-jest-3.0.4.tgz#b6a2b0d874968f26fa775ac901903fece531e08b" |