多语言开发中

This commit is contained in:
wanglin2 2022-10-28 16:26:55 +08:00
parent fadd8217e8
commit b46a94bd96
17 changed files with 323 additions and 70 deletions

View File

View File

@ -0,0 +1,3 @@
{
}

View File

@ -15,6 +15,7 @@
"element-ui": "^2.15.1",
"v-viewer": "^1.6.4",
"vue": "^2.6.11",
"vue-i18n": "^8.27.2",
"vue-router": "^3.5.1",
"vuex": "^3.6.2",
"xlsx": "^0.18.5"

View File

@ -379,3 +379,15 @@ export const shapeList = [
value: 'circle'
}
]
// 多语言列表
export const langList = [
{
value: 'zh',
name: '简体中文'
},
{
value: 'en',
name: 'English'
}
]

12
web/src/i18n.js Normal file
View File

@ -0,0 +1,12 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from './lang'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: 'zh',
messages
})
export default i18n

80
web/src/lang/en_us.js Normal file
View File

@ -0,0 +1,80 @@
export default {
baseStyle: {
title: 'BaseStyle',
background: 'Background',
color: 'Color',
image: 'Image',
imageRepeat: 'Image repeat',
line: 'Line',
width: 'Width',
style: 'Style',
lineOfOutline: 'Line of outline',
nodePadding: 'Node padding',
nodeMargin: 'Node margin',
horizontal: 'Horizontal',
vertical: 'Vertical',
maximumWidth: 'Max width',
maximumHeight: 'Max height',
icon: 'Icon',
size: 'Size',
level2Node: 'Level2 node',
belowLevel2Node: 'Below level2 node'
},
color: {
moreColor: 'More color'
},
contextmenu: {
insertSiblingNode: 'Insert sibling node',
insertChildNode: 'Insert child node',
insertSummary: 'Insert summary',
moveUpNode: 'Move up node',
moveDownNode: 'Move down node',
deleteNode: 'Delete node',
copyNode: 'Copy node',
cutNode: 'Cut node',
pasteNode: 'Paste node',
backCenter: 'Back center',
expandAll: 'Expand all',
unExpandAll: 'Un expand all',
expandTo: 'Expand to',
arrangeLayout: 'Arrange layout',
level1: 'Level1',
level2: 'Level2',
level3: 'Level3',
level4: 'Level4',
level5: 'Level5',
level6: 'Level6'
},
count: {
words: 'Words',
nodes: 'Nodes'
},
dialog: {
cancel: 'Cancel',
confirm: 'Confirm'
},
export: {
title: 'Export',
filename: 'Filename',
include: 'Is include config like theme and structure',
dedicatedFile: 'Dedicated file',
jsonFile: 'json file',
imageFile: 'Image file',
svgFile: 'svg file',
pdfFile: 'pdf file',
tips: 'tips.smm and .json file can be import'
},
fullscreen: {
fullscreen: 'Fullscreen'
},
import: {
title: 'Import',
selectFile: 'Select file',
supportFile: 'Support .smm、.json、.xmind、.xlsx file'
},
navigatorToolbar: {
openMiniMap: 'Open mini map',
readonly: 'Readonly',
edit: 'Edit'
}
}

7
web/src/lang/index.js Normal file
View File

@ -0,0 +1,7 @@
import en from './en_us'
import zh from './zh_cn'
export default {
zh,
en
}

80
web/src/lang/zh_cn.js Normal file
View File

@ -0,0 +1,80 @@
export default {
baseStyle: {
title: '基础样式',
background: '背景',
color: '颜色',
image: '图片',
imageRepeat: '图片重复',
line: '连线',
width: '粗细',
style: '风格',
lineOfOutline: '概要的连线',
nodePadding: '节点内边距',
nodeMargin: '节点外边距',
horizontal: '水平',
vertical: '垂直',
maximumWidth: '显示的最大宽度',
maximumHeight: '显示的最大高度',
icon: '图标',
size: '大小',
level2Node: '二级节点',
belowLevel2Node: '三级及以下节点'
},
color: {
moreColor: '更多颜色'
},
contextmenu: {
insertSiblingNode: '插入同级节点',
insertChildNode: '插入子级节点',
insertSummary: '插入概要',
moveUpNode: '上移节点',
moveDownNode: '下移节点',
deleteNode: '删除节点',
copyNode: '复制节点',
cutNode: '剪切节点',
pasteNode: '粘贴节点',
backCenter: '回到中心',
expandAll: '展开所有',
unExpandAll: '收起所有',
expandTo: '展开到',
arrangeLayout: '一键整理布局',
level1: '一级主题',
level2: '二级主题',
level3: '三级主题',
level4: '四级主题',
level5: '五级主题',
level6: '六级主题'
},
count: {
words: '字数',
nodes: '节点'
},
dialog: {
cancel: '取 消',
confirm: '确 定'
},
export: {
title: '导出',
filename: '导出文件名称',
include: '是否包含主题、结构等配置数据',
dedicatedFile: '专有文件',
jsonFile: 'json文件',
imageFile: '图片文件',
svgFile: 'svg文件',
pdfFile: 'pdf文件',
tips: 'tips.smm和.json文件可用于导入'
},
fullscreen: {
fullscreen: '全屏'
},
import: {
title: '导入',
selectFile: '选取文件',
supportFile: '支持.smm、.json、.xmind、.xlsx文件'
},
navigatorToolbar: {
openMiniMap: '开启小地图',
readonly: '只读模式',
edit: '编辑模式'
}
}

View File

@ -7,6 +7,7 @@ import 'element-ui/lib/theme-chalk/index.css'
import '@/assets/icon-font/iconfont.css'
import 'viewerjs/dist/viewer.css'
import VueViewer from 'v-viewer'
import i18n from './i18n'
Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()
@ -16,5 +17,6 @@ Vue.use(VueViewer)
new Vue({
render: h => h(App),
router,
store
store,
i18n
}).$mount('#app')

View File

@ -1,11 +1,11 @@
<template>
<Sidebar ref="sidebar" title="基础样式">
<Sidebar ref="sidebar" :title="$t('baseStyle.title')">
<div class="sidebarContent" v-if="data">
<!-- 背景 -->
<div class="title noTop">背景</div>
<div class="title noTop">{{ $t('baseStyle.background') }}</div>
<div class="row">
<el-tabs class="tab" v-model="activeTab">
<el-tab-pane label="颜色" name="color">
<el-tab-pane :label="$t('baseStyle.color')" name="color">
<Color
:color="style.backgroundColor"
@change="
@ -15,7 +15,7 @@
"
></Color>
</el-tab-pane>
<el-tab-pane label="图片" name="image">
<el-tab-pane :label="$t('baseStyle.image')" name="image">
<ImgUpload
class="imgUpload"
v-model="style.backgroundImage"
@ -26,7 +26,7 @@
"
></ImgUpload>
<div class="rowItem">
<span class="name">图片重复</span>
<span class="name">{{ $t('baseStyle.imageRepeat') }}</span>
<el-select
size="mini"
style="width: 120px"
@ -51,10 +51,10 @@
</el-tabs>
</div>
<!-- 连线 -->
<div class="title noTop">连线</div>
<div class="title noTop">{{ $t('baseStyle.line') }}</div>
<div class="row">
<div class="rowItem">
<span class="name">颜色</span>
<span class="name">{{ $t('baseStyle.color') }}</span>
<span
class="block"
v-popover:popover
@ -72,7 +72,7 @@
</el-popover>
</div>
<div class="rowItem">
<span class="name">粗细</span>
<span class="name">{{ $t('baseStyle.width') }}</span>
<el-select
size="mini"
style="width: 80px"
@ -96,7 +96,7 @@
</div>
<div class="row">
<div class="rowItem">
<span class="name">风格</span>
<span class="name">{{ $t('baseStyle.style') }}</span>
<el-select
size="mini"
style="width: 80px"
@ -119,10 +119,10 @@
</div>
</div>
<!-- 概要连线 -->
<div class="title noTop">概要的连线</div>
<div class="title noTop">{{ $t('baseStyle.lineOfOutline') }}</div>
<div class="row">
<div class="rowItem">
<span class="name">颜色</span>
<span class="name">{{ $t('baseStyle.color') }}</span>
<span
class="block"
v-popover:popover2
@ -140,7 +140,7 @@
</el-popover>
</div>
<div class="rowItem">
<span class="name">粗细</span>
<span class="name">{{ $t('baseStyle.width') }}</span>
<el-select
size="mini"
style="width: 80px"
@ -163,10 +163,10 @@
</div>
</div>
<!-- 内边距 -->
<div class="title noTop">节点内边距</div>
<div class="title noTop">{{ $t('baseStyle.nodePadding') }}</div>
<div class="row">
<div class="rowItem">
<span class="name">水平</span>
<span class="name">{{ $t('baseStyle.horizontal') }}</span>
<el-slider
style="width: 200px"
v-model="style.paddingX"
@ -180,7 +180,7 @@
</div>
<div class="row">
<div class="rowItem">
<span class="name">垂直</span>
<span class="name">{{ $t('baseStyle.vertical') }}</span>
<el-slider
style="width: 200px"
v-model="style.paddingY"
@ -193,10 +193,10 @@
</div>
</div>
<!-- 图片 -->
<div class="title noTop">图片</div>
<div class="title noTop">{{ $t('baseStyle.image') }}</div>
<div class="row">
<div class="rowItem">
<span class="name">显示的最大宽度</span>
<span class="name">{{ $t('baseStyle.maximumWidth') }}</span>
<el-slider
style="width: 140px"
v-model="style.imgMaxWidth"
@ -212,7 +212,7 @@
</div>
<div class="row">
<div class="rowItem">
<span class="name">显示的最大高度</span>
<span class="name">{{ $t('baseStyle.maximumHeight') }}</span>
<el-slider
style="width: 140px"
v-model="style.imgMaxHeight"
@ -227,10 +227,10 @@
</div>
</div>
<!-- 图标 -->
<div class="title noTop">图标</div>
<div class="title noTop">{{ $t('baseStyle.icon') }}</div>
<div class="row">
<div class="rowItem">
<span class="name">大小</span>
<span class="name">{{ $t('baseStyle.size') }}</span>
<el-slider
style="width: 200px"
v-model="style.iconSize"
@ -245,18 +245,24 @@
</div>
</div>
<!-- 二级节点外边距 -->
<div class="title noTop">节点外边距</div>
<div class="title noTop">{{ $t('baseStyle.nodeMargin') }}</div>
<div class="row column">
<el-tabs
class="tab"
v-model="marginActiveTab"
@tab-click="initMarginStyle"
>
<el-tab-pane label="二级节点" name="second"></el-tab-pane>
<el-tab-pane label="三级及以下节点" name="node"></el-tab-pane>
<el-tab-pane
:label="$t('baseStyle.level2Node')"
name="second"
></el-tab-pane>
<el-tab-pane
:label="$t('baseStyle.belowLevel2Node')"
name="node"
></el-tab-pane>
</el-tabs>
<div class="rowItem">
<span class="name">水平</span>
<span class="name">{{ $t('baseStyle.horizontal') }}</span>
<el-slider
:max="200"
style="width: 200px"
@ -269,7 +275,7 @@
></el-slider>
</div>
<div class="rowItem">
<span class="name">垂直</span>
<span class="name">{{ $t('baseStyle.vertical') }}</span>
<el-slider
:max="200"
style="width: 200px"

View File

@ -10,7 +10,7 @@
></span>
</div>
<div class="moreColor">
<span>更多颜色</span>
<span>{{ $t('color.moreColor') }}</span>
<el-color-picker
size="mini"
v-model="selectColor"

View File

@ -10,11 +10,11 @@
@click="exec('INSERT_NODE', insertNodeBtnDisabled)"
:class="{ disabled: insertNodeBtnDisabled }"
>
插入同级节点
{{ $t('contextmenu.insertSiblingNode') }}
<span class="desc">Enter</span>
</div>
<div class="item" @click="exec('INSERT_CHILD_NODE')">
插入子级节点
{{ $t('contextmenu.insertChildNode') }}
<span class="desc">Tab</span>
</div>
<div
@ -22,7 +22,7 @@
@click="exec('ADD_GENERALIZATION')"
:class="{ disabled: insertNodeBtnDisabled }"
>
插入概要
{{ $t('contextmenu.insertSummary') }}
<span class="desc">Ctrl + S</span>
</div>
<div
@ -30,7 +30,7 @@
@click="exec('UP_NODE')"
:class="{ disabled: upNodeBtnDisabled }"
>
上移节点
{{ $t('contextmenu.moveUpNode') }}
<span class="desc">Ctrl + </span>
</div>
<div
@ -38,19 +38,19 @@
@click="exec('DOWN_NODE')"
:class="{ disabled: downNodeBtnDisabled }"
>
下移节点
{{ $t('contextmenu.moveDownNode') }}
<span class="desc">Ctrl + </span>
</div>
<div class="item danger" @click="exec('REMOVE_NODE')">
删除节点
{{ $t('contextmenu.deleteNode') }}
<span class="desc">Delete</span>
</div>
<div class="item" @click="exec('COPY_NODE')">
复制节点
{{ $t('contextmenu.copyNode') }}
<span class="desc">Ctrl + C</span>
</div>
<div class="item" @click="exec('CUT_NODE')">
剪切节点
{{ $t('contextmenu.cutNode') }}
<span class="desc">Ctrl + X</span>
</div>
<div
@ -58,16 +58,22 @@
:class="{ disabled: copyData === null }"
@click="exec('PASTE_NODE')"
>
粘贴节点
{{ $t('contextmenu.pasteNode') }}
<span class="desc">Ctrl + V</span>
</div>
</template>
<template v-if="type === 'svg'">
<div class="item" @click="exec('RETURN_CENTER')">回到中心</div>
<div class="item" @click="exec('EXPAND_ALL')">展开所有</div>
<div class="item" @click="exec('UNEXPAND_ALL')">收起所有</div>
<div class="item" @click="exec('RETURN_CENTER')">
{{ $t('contextmenu.backCenter') }}
</div>
<div class="item" @click="exec('EXPAND_ALL')">
{{ $t('contextmenu.expandAll') }}
</div>
<div class="item" @click="exec('UNEXPAND_ALL')">
{{ $t('contextmenu.unExpandAll') }}
</div>
<div class="item">
展开到
{{ $t('contextmenu.expandTo') }}
<div class="subItems listBox">
<div
class="item"
@ -80,7 +86,7 @@
</div>
</div>
<div class="item" @click="exec('RESET_LAYOUT')">
一键整理布局
{{ $t('contextmenu.arrangeLayout') }}
<span class="desc">Ctrl + L</span>
</div>
</template>
@ -112,12 +118,12 @@ export default {
mosuedownX: 0,
mosuedownY: 0,
expandList: [
'一级主题',
'二级主题',
'三级主题',
'四级主题',
'五级主题',
'六级主题'
this.$t('contextmenu.level1'),
this.$t('contextmenu.level2'),
this.$t('contextmenu.level3'),
this.$t('contextmenu.level4'),
this.$t('contextmenu.level5'),
this.$t('contextmenu.level6')
]
}
},

View File

@ -1,11 +1,11 @@
<template>
<div class="countContainer">
<div class="item">
<span class="name">字数</span>
<span class="name">{{ $t('count.words') }}</span>
<span class="value">{{ words }}</span>
</div>
<div class="item">
<span class="name">节点</span>
<span class="name">{{ $t('count.nodes') }}</span>
<span class="value">{{ num }}</span>
</div>
</div>

View File

@ -1,13 +1,13 @@
<template>
<el-dialog
class="nodeDialog"
title="导出"
:title="$t('export.title')"
:visible.sync="dialogVisible"
width="700px"
>
<div>
<div class="nameInputBox">
<span class="name">导出文件名称</span>
<span class="name">{{ $t('export.filename') }}</span>
<el-input
style="width: 300px"
v-model="fileName"
@ -17,21 +17,33 @@
v-show="['smm', 'json'].includes(exportType)"
v-model="widthConfig"
style="margin-left: 12px"
>是否包含主题结构等配置数据</el-checkbox
>{{ $t('export.include') }}</el-checkbox
>
</div>
<el-radio-group v-model="exportType" size="mini">
<el-radio-button label="smm">专有文件.smm</el-radio-button>
<el-radio-button label="json">json文件.json</el-radio-button>
<el-radio-button label="png">图片文件.png</el-radio-button>
<el-radio-button label="svg">svg文件.svg</el-radio-button>
<el-radio-button label="pdf">pdf文件.pdf</el-radio-button>
<el-radio-button label="smm"
>{{ $t('export.dedicatedFile') }}.smm</el-radio-button
>
<el-radio-button label="json"
>{{ $t('export.jsonFile') }}.json</el-radio-button
>
<el-radio-button label="png"
>{{ $t('export.imageFile') }}.png</el-radio-button
>
<el-radio-button label="svg"
>{{ $t('export.svgFile') }}.svg</el-radio-button
>
<el-radio-button label="pdf"
>{{ $t('export.pdfFile') }}.pdf</el-radio-button
>
</el-radio-group>
<div class="tip">tips.smm和.json文件可用于导入</div>
<div class="tip">{{ $t('export.tips') }}</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="confirm"> </el-button>
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
<el-button type="primary" @click="confirm">{{
$t('dialog.confirm')
}}</el-button>
</span>
</el-dialog>
</template>

View File

@ -1,6 +1,11 @@
<template>
<div class="fullscreenContainer">
<el-tooltip class="item" effect="dark" content="全屏" placement="top">
<el-tooltip
class="item"
effect="dark"
:content="$t('fullscreen.fullscreen')"
placement="top"
>
<div class="btn iconfont iconquanping" @click="toFullscreen"></div>
</el-tooltip>
</div>

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
class="nodeDialog"
title="导入"
:title="$t('import.title')"
:visible.sync="dialogVisible"
width="300px"
>
@ -15,14 +15,18 @@
:limit="1"
:on-exceed="onExceed"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button slot="trigger" size="small" type="primary">{{
$t('import.selectFile')
}}</el-button>
<div slot="tip" class="el-upload__tip">
支持.smm.json.xmind.xlsx文件
{{ $t('import.supportFile') }}
</div>
</el-upload>
<span slot="footer" class="dialog-footer">
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="confirm"> </el-button>
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
<el-button type="primary" @click="confirm">{{
$t('dialog.confirm')
}}</el-button>
</span>
</el-dialog>
</template>

View File

@ -1,15 +1,30 @@
<template>
<div class="navigatorContainer">
<div class="item">
<el-checkbox v-model="openMiniMap" @change="toggleMiniMap"
>开启小地图</el-checkbox
<el-select
v-model="lang"
size="small"
style="width: 100px"
@change="onLangChange"
>
<el-option
v-for="item in langList"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</div>
<div class="item">
<el-checkbox v-model="openMiniMap" @change="toggleMiniMap">{{
$t('navigatorToolbar.openMiniMap')
}}</el-checkbox>
</div>
<div class="item">
<el-switch
v-model="isReadonly"
active-text="只读模式"
inactive-text="编辑模式"
:active-text="$t('navigatorToolbar.readonly')"
:inactive-text="$t('navigatorToolbar.edit')"
@change="readonlyChange"
>
</el-switch>
@ -26,6 +41,8 @@
<script>
import Scale from './Scale'
import Fullscreen from './Fullscreen'
import { langList } from '@/config'
import i18n from '@/i18n'
/**
* @Author: 王林
@ -45,6 +62,8 @@ export default {
},
data() {
return {
langList,
lang: 'zh',
isReadonly: false,
openMiniMap: false
}
@ -59,6 +78,10 @@ export default {
toggleMiniMap(show) {
this.$bus.$emit('toggle_mini_map', show)
},
onLangChange(lang) {
i18n.locale = lang
}
}
}