From 0db13c8506ba75014570be7dc7b72a173714d7b0 Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 28 Nov 2018 15:21:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=9B=BD=E9=99=85=E5=8C=96?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/History.md | 17 ++++ gulpfile.js | 3 + locale/de.json | 38 +++++++ locale/en.json | 38 +++++++ locale/zh_CN.json | 38 +++++++ locale/zh_TW.json | 38 +++++++ main.js | 2 +- package.json | 10 +- src/js/common.js | 229 ++++------------------------------------- src/js/config.js | 124 ++++++++++++++++++++++ src/js/i18n.js | 42 ++++++++ src/js/index.js | 85 ++++++++-------- src/js/menu-bar.js | 243 ++++++++++++++++++++++---------------------- src/js/open-file.js | 2 +- src/js/shortcut.js | 73 +++++++++++++ version.js | 2 +- 16 files changed, 604 insertions(+), 380 deletions(-) create mode 100644 locale/de.json create mode 100644 locale/en.json create mode 100644 locale/zh_CN.json create mode 100644 locale/zh_TW.json create mode 100644 src/js/config.js create mode 100644 src/js/i18n.js create mode 100644 src/js/shortcut.js diff --git a/doc/History.md b/doc/History.md index cdd4eab..e361bfe 100644 --- a/doc/History.md +++ b/doc/History.md @@ -2,8 +2,25 @@ [**桌面版脑图**](https://github.com/NaoTu/DesktopNaotu) 是百度脑图的离线版,帮助你在没有互联网环境的情况下,依然可以使用脑图工具。 +## 各版本对应的系统 + +| 操作系统 | 位数 | 对应文件 | 大小 | 支持情况 | +| -------- | -----: | -----: | :---- | -- | +| MacOS | 64位 | DesktopNaotu-macOS-x64 | < 50M | 支持全部功能 | +| Linux | 64位 | DesktopNaotu-linux-x64 | < 50M | 支持全部功能 | +| Windows 7/10 | 64位 | DesktopNaotu-win32-x64 | < 50M | 支持全部功能 | +| Windows 7/10 | 32位 | DesktopNaotu-win32-ia32 | < 50M | 支持全部功能 | +| Windows XP | 32位 | DesktopNaotu-Windows-mini | < 8M | 不支持调试 | + ## 更新记录 +### 3.0.0 / 2018-11-28 + +- 正式支持多语言。`鸣谢:涛` + - 初版支持中文简体、中文繁体、英文 + - 软件的语言默认基于系统语言设置,也可以通过修改配置文件来强制改变 +- 修复其他小问题 + ### 2.1.1 / 2018-11-22 - 修复 上传本地图片后无法导出png的问题。 diff --git a/gulpfile.js b/gulpfile.js index 14a4b41..94ab943 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -64,6 +64,9 @@ gulp.task('bower', function () { // }); gulp.task('copy-js-vendor', function () { + // i18n + gulp.src(["locale/*.json"]).pipe(gulp.dest('dist/locale')); + // 解决需要引入的问题,单独处理 gulp.src(["bower_components/jquery/dist/jquery.min.js"]) .pipe(gulp.dest('dist/js')); diff --git a/locale/de.json b/locale/de.json new file mode 100644 index 0000000..f1003e4 --- /dev/null +++ b/locale/de.json @@ -0,0 +1,38 @@ +{ + "mFile": "&File", + "miNewFile": "&New File", + "miOpenFile": "&Open File...", + "miOpenFolder": "Open &Folder...", + "miOpenRecent": "Open &Recent", + "miClearRecent": "&Clear Recently Opened", + "miSave": "&Save", + "miSaveAs": "Save &As...", + "miExport": "&Export...", + "miAutoSave": "A&uto Save", + "miSavePath": "Re-select the automatically saved directory(&R)", + "miExit": "E&xit", + "mEdit": "&Edit", + "miUndo": "&Undo", + "miRedo": "&Redo", + "miCut": "Cu&t", + "miCopy": "&Copy", + "miPaste": "&Paste", + "mWindow": "&Window", + "miMaxWin": "Ma&ximize", + "miMinWin": "Mi&nimise", + "mHelp": "&Help", + "miShortcut": "&Keyboard Shortcuts", + "miBackup": "Help document(&V)", + "miCheckVer": "Check for &Updates...", + "miAbout": "&About", + "sMainTopic": "Main Topic", + "sLoadedError": "Failed to load the file! Only support .km format file!", + "sNoFileLocation": "file does not exist", + "sNoUpdatesAvailable": "no updates available.", + "sAppName": "Desktop Naotu", + "sUpdateMessage": "A new version has been detected, please download the new version.", + "sExportKm": "Export .Km", + "sSaveKm": "Save .Km", + "sNoOpenFile": "You have not opened any files yet.", + "sNewKm": "New file will close the current file, continue?" +} diff --git a/locale/en.json b/locale/en.json new file mode 100644 index 0000000..f1003e4 --- /dev/null +++ b/locale/en.json @@ -0,0 +1,38 @@ +{ + "mFile": "&File", + "miNewFile": "&New File", + "miOpenFile": "&Open File...", + "miOpenFolder": "Open &Folder...", + "miOpenRecent": "Open &Recent", + "miClearRecent": "&Clear Recently Opened", + "miSave": "&Save", + "miSaveAs": "Save &As...", + "miExport": "&Export...", + "miAutoSave": "A&uto Save", + "miSavePath": "Re-select the automatically saved directory(&R)", + "miExit": "E&xit", + "mEdit": "&Edit", + "miUndo": "&Undo", + "miRedo": "&Redo", + "miCut": "Cu&t", + "miCopy": "&Copy", + "miPaste": "&Paste", + "mWindow": "&Window", + "miMaxWin": "Ma&ximize", + "miMinWin": "Mi&nimise", + "mHelp": "&Help", + "miShortcut": "&Keyboard Shortcuts", + "miBackup": "Help document(&V)", + "miCheckVer": "Check for &Updates...", + "miAbout": "&About", + "sMainTopic": "Main Topic", + "sLoadedError": "Failed to load the file! Only support .km format file!", + "sNoFileLocation": "file does not exist", + "sNoUpdatesAvailable": "no updates available.", + "sAppName": "Desktop Naotu", + "sUpdateMessage": "A new version has been detected, please download the new version.", + "sExportKm": "Export .Km", + "sSaveKm": "Save .Km", + "sNoOpenFile": "You have not opened any files yet.", + "sNewKm": "New file will close the current file, continue?" +} diff --git a/locale/zh_CN.json b/locale/zh_CN.json new file mode 100644 index 0000000..19438c6 --- /dev/null +++ b/locale/zh_CN.json @@ -0,0 +1,38 @@ +{ + "mFile": "文件(&F)", + "miNewFile": "新建文件(&N)", + "miOpenFile": "打开文件(&O)...", + "miOpenFolder": "打开文件夹(&F)...", + "miOpenRecent": "打开最近的文件(&R)", + "miClearRecent": "清除最近打开记录", + "miSave": "保存(&S)", + "miSaveAs": "另存为(&A)...", + "miExport": "导出(&E)...", + "miAutoSave": "自动保存", + "miSavePath": "重选自动保存的目录(&R)", + "miExit": "退出(&X)", + "mEdit": "编辑(&E)", + "miUndo": "撤销(&U)", + "miRedo": "恢复(&R)", + "miCut": "剪切(&T)", + "miCopy": "复制(&C)", + "miPaste": "粘贴(&P)", + "mWindow": "窗口(&W)", + "miMaxWin": "最大化(&X)", + "miMinWin": "最小化(&N)", + "mHelp": "帮助(&H)", + "miShortcut": "快捷键(&H)...", + "miBackup": "备份百度脑图到本地(&V)", + "miCheckVer": "检查更新...(&N)", + "miAbout": "关于(&A)", + "sMainTopic": "中心主题", + "sLoadedError": "加载文件失败!只允许打开.km格式的文件!", + "sNoFileLocation": "文件路径不存在", + "sNoUpdatesAvailable": "当前没有可用的更新。", + "sAppName": "桌面版脑图", + "sUpdateMessage": "检测到新版本,请下载新版本。", + "sExportKm": "导出 KityMinder 文件", + "sSaveKm": "保存 KityMinder 文件", + "sNoOpenFile": "您当前还未打开任何文件。", + "sNewKm": "新建文件会关闭当前文件,是否继续?" +} diff --git a/locale/zh_TW.json b/locale/zh_TW.json new file mode 100644 index 0000000..366c598 --- /dev/null +++ b/locale/zh_TW.json @@ -0,0 +1,38 @@ +{ + "mFile": "文件(&F)", + "miNewFile": "新建文件(&N)", + "miOpenFile": "打開文件(&O)...", + "miOpenFolder": "打開文件夾(&F)...", + "miOpenRecent": "打開最近的文件(&R)", + "miClearRecent": "清除最近打開記錄", + "miSave": "保存(&S)", + "miSaveAs": "另存為(&A)...", + "miExport": "導出(&E)...", + "miAutoSave": "自動保存", + "miSavePath": "重選自動保存的目錄(&R)", + "miExit": "退出(&X)", + "mEdit": "編輯(&E)", + "miUndo": "撤銷(&U)", + "miRedo": "恢復(&R)", + "miCut": "剪切(&T)", + "miCopy": "複製(&C)", + "miPaste": "粘貼(&P)", + "mWindow": "窗口(&W)", + "miMaxWin": "最大化(&X)", + "miMinWin": "最小化(&N)", + "mHelp": "幫助(&H)", + "miShortcut": "快捷鍵(&H)...", + "miBackup": "備份百度腦圖到本地(&V)", + "miCheckVer": "檢查更新...(&N)", + "miAbout": "關於(&A)", + "sMainTopic": "中心主題", + "sLoadedError": "加載文件失敗!只允許打開.km格式的文件!", + "sNoFileLocation": "文件路徑不存在", + "sNoUpdatesAvailable": "當前沒有可用的更新。", + "sAppName": "桌面版腦圖", + "sUpdateMessage": "檢測到新版本,請下載新版本。", + "sExportKm": "導出 KityMinder 文件", + "sSaveKm": "保存 KityMinder 文件", + "sNoOpenFile": "您當前還未打開任何文件。", + "sNewKm": "新建文件會關閉當前文件,是否繼續?" +} diff --git a/main.js b/main.js index 5c32290..bad92ca 100644 --- a/main.js +++ b/main.js @@ -22,7 +22,7 @@ function createWindow() { 'fullscreenable': true, 'show': false, - 'icon': `${__dirname}/favicon.png`, + 'icon': `${__dirname}/favicon.ico`, 'backgroundColor': '#fbfbfb' }); diff --git a/package.json b/package.json index 38b8fe2..1d439fc 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "desktopnaotu", - "version": "2.1.1", + "version": "3.0.0", "description": "桌面版脑图", "main": "main.js", "scripts": { "start": "gulp default && electron main.js", - "packwin32": "electron-packager ./ DesktopNaotu --platform=win32 --arch=ia32 --out=../OutApp --icon=favicon.ico --electron-version=3.0.10 --app-version=2.1.1 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", - "packwin64": "electron-packager ./ DesktopNaotu --platform=win32 --arch=x64 --out=../OutApp --icon=favicon.ico --electron-version=3.0.10 --app-version=2.1.1 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", - "packmacos": "electron-packager ./ DesktopNaotu --platform=darwin --arch=x64 --out=../OutApp --icon=favicon.icns --electron-version=3.0.10 --app-version=2.1.1 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", - "packlinux": "electron-packager ./ DesktopNaotu --platform=linux --arch=x64 --out=../OutApp --icon=favicon.png --electron-version=3.0.10 --app-version=2.1.1 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune" + "packwin32": "electron-packager ./ DesktopNaotu --platform=win32 --arch=ia32 --out=../OutApp --icon=favicon.ico --electron-version=3.0.10 --app-version=3.0.0 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", + "packwin64": "electron-packager ./ DesktopNaotu --platform=win32 --arch=x64 --out=../OutApp --icon=favicon.ico --electron-version=3.0.10 --app-version=3.0.0 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", + "packmacos": "electron-packager ./ DesktopNaotu --platform=darwin --arch=x64 --out=../OutApp --icon=favicon.icns --electron-version=3.0.10 --app-version=3.0.0 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune", + "packlinux": "electron-packager ./ DesktopNaotu --platform=linux --arch=x64 --out=../OutApp --icon=favicon.png --electron-version=3.0.10 --app-version=3.0.0 --ignore=\"(.git|screenshot|doc|src|bower_components|electron-packager)\" --overwrite --prune" }, "repository": { "type": "git", diff --git a/src/js/common.js b/src/js/common.js index 720b736..7d84f63 100644 --- a/src/js/common.js +++ b/src/js/common.js @@ -1,7 +1,7 @@ var defaultPath = null, isSutoSave = true, fs = require("fs"), - { remote, globalShortcut, shell } = require("electron"), + { remote, globalShortcut, shell, electron } = require("electron"), { dialog, Menu, app } = require("electron").remote, { BrowserWindow, Menu, MenuItem } = require("electron").remote, ver = require("../version"), @@ -28,7 +28,9 @@ log4js.configure({ const logger = log4js.getLogger("NaoTuApp"); var confPath = path.join(getUserDataDir(), "/naotu.config.json"); +// init $(function() { + getAppInstance().setTitle(i18n.__("sAppName")); bootbox.setLocale("zh_CN"); // 欢迎语 @@ -117,7 +119,7 @@ function newDialog() { if (hasData()) { bootbox.confirm({ - message: "新建文件会关闭当前文件,是否继续?", + message: i18n.__("sNewKm"), callback: function(result) { if (result) { initRoot(); @@ -133,14 +135,14 @@ function hasData() { var nodes = editor.minder.getAllNode().length; var rootText = editor.minder.getRoot().data.text; - return nodes != 1 || rootText != "中心主题"; + return nodes != 1 || rootText != i18n.__("sMainTopic"); } function initRoot() { defaultPath = null; - getAppInstance().setTitle("桌面版脑图"); + getAppInstance().setTitle(i18n.__("sAppName")); editor.minder.importJson({ - root: { data: { text: "中心主题" } }, + root: { data: { text: i18n.__("sMainTopic") } }, template: "filetree", theme: "fresh-blue" }); @@ -168,7 +170,7 @@ function openFileInFolder() { if (defaultPath != null) { shell.showItemInFolder(defaultPath); } else { - bootbox.alert("您当前还未打开任何文件。"); + bootbox.alert(i18n.__("sNoOpenFile")); } } @@ -190,7 +192,7 @@ function saveAsDialog() { dialog.showSaveDialog( { - title: "保存 KityMinder 文件", + title: i18n.__("sSaveKm"), defaultPath: newPath, filters: [{ name: "KityMinder", extensions: ["km"] }] }, @@ -224,7 +226,7 @@ function exportDialog() { dialog.showSaveDialog( { - title: "导出 KityMinder 文件", + title: i18n.__("sExportKm"), defaultPath: newPath, filters: filters }, @@ -285,7 +287,9 @@ function minwin() { } function license() { - shell.openExternal("https://github.com/NaoTu/DesktopNaotu/blob/master/doc/Help.md"); + shell.openExternal( + "https://github.com/NaoTu/DesktopNaotu/blob/master/doc/Help.md" + ); } function checkVersion() { @@ -298,10 +302,10 @@ function checkVersion() { var oldVer = ver.version.slice(0, 3).join(", "); if (newVer != oldVer) { - bootbox.alert("检测到新版本,请下载新版本。"); + bootbox.alert(i18n.__("sUpdateMessage")); shell.openExternal("https://github.com/NaoTu/DesktopNaotu/releases"); } else { - bootbox.alert("当前没有可用的更新。"); + bootbox.alert(i18n.__("sNoUpdatesAvailable")); } } ); @@ -313,85 +317,10 @@ Copyright (c) 2018 Jack 版本: v${ver.version.join(".")} QQ 讨论群:330722928 -需要下载百度脑图文件,请点击:查看帮助 `; dialog.showMessageBox({ type: "info", - title: "桌面版脑图", - message: text, - buttons: ["OK"] - }); -} - -function shortcut() { - var shortcutKeys = [ - { - groupName: "节点操作", - groupItem: [ - { key: "Enter", desc: " 插入兄弟节点" }, - { key: "Tab, Insert", desc: " 插入子节点" }, - { key: "Shift + Tab", desc: " 插入父节点" }, - { key: "Delete", desc: " 删除节点" }, - { key: "Up, Down, Left, Right", desc: " 节点导航" }, - { key: "Alt + Up, Down", desc: " 向上/向下调整顺序" }, - { key: "/", desc: " 展开/收起节点" }, - { key: "F2", desc: " 编辑节点" }, - { key: "Shift + Enter", desc: " 文本换行" }, - { key: "Ctrl + A", desc: " 全选节点" }, - { key: "Ctrl + C", desc: " 复制节点" }, - { key: "Ctrl + X", desc: " 剪切节点" }, - { key: "Ctrl + V", desc: " 粘贴节点" }, - { key: "Ctrl + B", desc: " 加粗" }, - { key: "Ctrl + I", desc: " 斜体" }, - { key: "Ctrl + F", desc: " 查找节点" } - ] - }, - { - groupName: "视野控制", - groupItem: [ - //{ key:"Ctrl + ESC",desc:" 全屏切换"}, - { key: "Alt + 拖动, 右键拖动", desc: " 拖动视野" }, - { key: "滚轮, 触摸板", desc: " 移动视野" }, - //{ key:"Ctrl + Up, Down, Left, Right",desc:" 视野导航"}, - { key: "空白处双击, Ctrl + Enter", desc: " 居中根节点" }, - { key: "Ctrl + +, -", desc: " 放大/缩小视野" } - ] - }, - { - groupName: "文件操作", - groupItem: [ - { key: "Ctrl + O", desc: " 打开" }, - { key: "Ctrl + S", desc: " 保存" }, - { key: "Ctrl + Shift + S", desc: " 另存为" } - // { key: "Ctrl + Alt + S", desc: " 分享" } - ] - }, - { - groupName: "布局", - groupItem: [{ key: "Ctrl + Shift + L", desc: " 整理布局" }] - }, - { - groupName: "后悔药", - groupItem: [ - { key: "Ctrl + Z", desc: " 撤销" }, - { key: "Ctrl + Y", desc: " 重做" } - ] - } - ]; - - var text = ""; - for (var i = 0; i < shortcutKeys.length; i++) { - var group = shortcutKeys[i]; - text += `\n` + group.groupName + `\n`; - for (var j = 0; j < group.groupItem.length; j++) { - var item = group.groupItem[j]; - text += ` ` + item.desc + ` ` + item.key + `\n`; - } - } - - dialog.showMessageBox({ - type: "none", - title: "快捷键", + title: i18n.__("sAppName"), message: text, buttons: ["OK"] }); @@ -455,7 +384,7 @@ function showFileName(fileName) { fileName.lastIndexOf("\\") > -1 ? fileName.lastIndexOf("\\") : fileName.lastIndexOf("/"); - var title = fileName.substring(index + 1) + " - 桌面版脑图"; + var title = fileName.substring(index + 1) + " - " + i18n.__("sAppName"); getAppInstance().setTitle(title); } @@ -464,127 +393,3 @@ function showFileName(fileName) { function getAppInstance() { return BrowserWindow.getAllWindows()[0]; } - -function getDefConf() { - return { - defSavePath: getUserDataDir(), - recently: [] - }; -} - -function clearRecently() { - try { - // 读取配置文件 - var confObj = JSON.parse(fs.readFileSync(confPath)); - if (confObj != null) { - // 清空历史记录的列表 - confObj.recently = []; - - fs.writeFileSync(confPath, JSON.stringify(confObj)); - } else { - // 读失败了,则创建一个默认的配置文件 - fs.writeFileSync(confPath, JSON.stringify(getDefConf())); - } - - // 更新菜单 - updateMenus(); - } catch (ex) { - logger.error(ex); - } -} - -function saveRecords(filePath) { - var time = new Date().format("yyyy-MM-dd hh:mm:ss"); - - fs.exists(confPath, function(exists) { - if (!exists) { - // 不存在,则创建 - var confObj = getDefConf(); - confObj.recently.push({ time: time, path: filePath }); - - fs.writeFileSync(confPath, JSON.stringify(confObj)); - } else { - // 存在,则读取 - var confObj = JSON.parse(fs.readFileSync(confPath)); - var list = confObj.recently; - - // 查重 - var items = [], - selected = null; - for (var i = 0; i < list.length; i++) { - var item = list[i]; - if (item.path == filePath) { - selected = item; - } else { - items.push(item); - } - } - - if (selected == null) { - items.splice(0, 0, { time: time, path: filePath }); - } else { - // 在原来的清单中,则更新 - selected.time = time; - items.splice(0, 0, selected); - } - - confObj.recently = items; - - // 更新列表 - fs.writeFileSync(confPath, JSON.stringify(confObj)); - } - }); - - // 更新菜单 - updateMenus(); -} - -function updateMenus() { - fs.exists(confPath, function(exists) { - if (exists) { - // 存在,则读取 - - // 深度复制 - var menus = $.extend(true, [], template); - - var confObj = JSON.parse(fs.readFileSync(confPath)); - var list = confObj.recently; - - for (var i = 0; i < Math.min(list.length, 5); i++) { - // 只显示最近5次 - var item = list[i]; - - // 追加到菜单 - menus[0].submenu[4].submenu.splice( - menus[0].submenu[4].submenu.length - 2, - 0, - { - label: item.path, - click: openRecently - } - ); - } - - // 更新菜单 - var menu = Menu.buildFromTemplate(menus); - Menu.setApplicationMenu(menu); - } else { - var menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); - } - }); -} - -function openRecently(item) { - var path = item.label; - if (path) { - fs.exists(path, function(result) { - if (result) { - // 存在,则读取 - readFile(path); - } else { - bootbox.alert("文件路径不存在"); - } - }); - } -} diff --git a/src/js/config.js b/src/js/config.js new file mode 100644 index 0000000..6c12ce9 --- /dev/null +++ b/src/js/config.js @@ -0,0 +1,124 @@ +function getDefConf() { + return { + locale: app.getLocale(), + defSavePath: getUserDataDir(), + recently: [] + }; +} + +function clearRecently() { + try { + // 读取配置文件 + var confObj = JSON.parse(fs.readFileSync(confPath)); + if (confObj != null) { + // 清空历史记录的列表 + confObj.recently = []; + + fs.writeFileSync(confPath, JSON.stringify(confObj)); + } else { + // 读失败了,则创建一个默认的配置文件 + fs.writeFileSync(confPath, JSON.stringify(getDefConf())); + } + + // 更新菜单 + updateMenus(); + } catch (ex) { + logger.error(ex); + } +} + +function saveRecords(filePath) { + var time = new Date().format("yyyy-MM-dd hh:mm:ss"); + + fs.exists(confPath, function(exists) { + if (!exists) { + // 不存在,则创建 + var confObj = getDefConf(); + confObj.recently.push({ time: time, path: filePath }); + + fs.writeFileSync(confPath, JSON.stringify(confObj)); + } else { + // 存在,则读取 + var confObj = JSON.parse(fs.readFileSync(confPath)); + var list = confObj.recently; + + // 查重 + var items = [], + selected = null; + for (var i = 0; i < list.length; i++) { + var item = list[i]; + if (item.path == filePath) { + selected = item; + } else { + items.push(item); + } + } + + if (selected == null) { + items.splice(0, 0, { time: time, path: filePath }); + } else { + // 在原来的清单中,则更新 + selected.time = time; + items.splice(0, 0, selected); + } + + confObj.recently = items; + + // 更新列表 + fs.writeFileSync(confPath, JSON.stringify(confObj)); + } + }); + + // 更新菜单 + updateMenus(); +} + +function updateMenus() { + fs.exists(confPath, function(exists) { + if (exists) { + // 存在,则读取 + + // 深度复制 + var menus = $.extend(true, [], template); + + var confObj = JSON.parse(fs.readFileSync(confPath)); + var list = confObj.recently; + + for (var i = 0; i < Math.min(list.length, 5); i++) { + // 只显示最近5次 + var item = list[i]; + + // 追加到菜单 + menus[0].submenu[4].submenu.splice( + menus[0].submenu[4].submenu.length - 2, + 0, + { + label: item.path, + click: openRecently + } + ); + } + + // 更新菜单 + var menu = Menu.buildFromTemplate(menus); + Menu.setApplicationMenu(menu); + } else { + var menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + } + }); +} + +function openRecently(item) { + var path = item.label; + if (path) { + fs.exists(path, function(result) { + if (result) { + // 存在,则读取 + readFile(path); + } else { + bootbox.alert(i18n.__("sNoFileLocation")); + } + }); + } +} diff --git a/src/js/i18n.js b/src/js/i18n.js new file mode 100644 index 0000000..5724700 --- /dev/null +++ b/src/js/i18n.js @@ -0,0 +1,42 @@ +// i18n https://www.christianengvall.se/electron-localization/ +let loadedLanguage; +var i18n = { + lang: function() { + var lang = "en"; + + try { + var confObj = JSON.parse(fs.readFileSync(confPath)); + if (confObj == null) { + confObj = getDefConf(); + } + + lang = confObj.locale.replace("-", "_"); + } catch (error) {} + + return lang; + }, + __: function(phrase) { + if (loadedLanguage == undefined) { + var folder = "locale"; + + if (fs.existsSync(path.join(__dirname, folder, i18n.lang() + ".json"))) { + loadedLanguage = JSON.parse( + fs.readFileSync( + path.join(__dirname, folder, i18n.lang() + ".json"), + "utf8" + ) + ); + } else { + loadedLanguage = JSON.parse( + fs.readFileSync(path.join(__dirname, folder, "en.json"), "utf8") + ); + } + } + + let translation = loadedLanguage[phrase]; + if (translation === undefined) { + translation = phrase; + } + return translation; + } +}; diff --git a/src/js/index.js b/src/js/index.js index cbd4809..b0a6f11 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,44 +1,47 @@ // window.$ = window.jQuery = require('../bower_components/jquery/dist/jquery.min.js'); -window.$ = window.jQuery = require('./js/jquery.min.js'); - -var remote = require('electron').remote, - argv = remote.getGlobal('sharedObject').prop1; - -angular.module('kityminderDemo', ['kityminderEditor']).config(function (configProvider) { - configProvider.set('imageUpload', '../server/imageUpload.php'); - - if (argv.length >= 2) { - let filePath = argv[1]; - - //open, read, handle file - if (filePath.indexOf('km') > -1) { - readFile(filePath); - } - } - -}).controller('MainController', function ($scope, $modal) { - $scope.initEditor = function (editor, minder) { - window.editor = editor; - window.minder = minder; +window.$ = window.jQuery = require("./js/jquery.min.js"); + +var remote = require("electron").remote, + argv = remote.getGlobal("sharedObject").prop1; + +angular + .module("kityminderDemo", ["kityminderEditor"]) + .config(function(configProvider) { + configProvider.set("lang", i18n.lang()); + // configProvider.set('imageUpload', '../server/imageUpload.php'); + + // if (argv.length >= 2) { + // let filePath = argv[1]; + + // //open, read, handle file + // if (filePath.indexOf('km') > -1) { + // readFile(filePath); + // } + // } + }) + .controller("MainController", function($scope, $modal) { + $scope.initEditor = function(editor, minder) { + window.editor = editor; + window.minder = minder; }; + }); + +window.$(function() { + if (minder != null) { + // auto saving + minder.on("contentchange", function() { + if (isSutoSave) { + saveDialog(); + } + }); + + minder.on("selectionchange", function() { + var node = minder.getSelectedNode(); + + var menu = remote.Menu.getApplicationMenu(); + + // 对编辑菜单进行管理 + menu.items[1].submenu.items[3].enabled = menu.items[1].submenu.items[4].enabled = menu.items[1].submenu.items[5].enabled = !!node; + }); + } }); - -window.$(function () { - if (minder != null) {// auto saving - minder.on('contentchange', function () { - if (isSutoSave) { - saveDialog(); - } - }); - - minder.on('selectionchange', function () { - var node = minder.getSelectedNode(); - - // 对编辑菜单进行管理 - menu.items[1].submenu.items[3].enabled = - menu.items[1].submenu.items[4].enabled = - menu.items[1].submenu.items[5].enabled = !!node; - - }); - } -}); \ No newline at end of file diff --git a/src/js/menu-bar.js b/src/js/menu-bar.js index 60775c6..ce50ae7 100644 --- a/src/js/menu-bar.js +++ b/src/js/menu-bar.js @@ -1,132 +1,137 @@ -var remote = require('electron').remote; +var remote = require("electron").remote; var Menu = remote.Menu; -var template = [{ - label: '文件(&F)', +var template = [ + { + label: i18n.__("mFile"), submenu: [ - { - label: '新建文件(&N)', - accelerator: 'CmdOrCtrl+N', - click: newDialog - }, - { - label: '打开文件(&O)', - accelerator: 'CmdOrCtrl+O', - click: openDialog - }, - { type: 'separator' }, - { - label: '在文件夹中打开文件(&L)', - accelerator: 'CmdOrCtrl+Shift+O', - click: openFileInFolder - }, - { - label: '打开最近的文件(&R)', - submenu: [ - { type: 'separator' }, - { - id: 1, - label: '清除最近打开记录', - click: clearRecently - } - ] - }, - { type: 'separator' }, - { - label: '保存(&S)', - accelerator: 'CmdOrCtrl+S', - click: saveDialog - }, - { - label: '另存为(&A)...', - accelerator: 'CmdOrCtrl+Shift+S', - click: saveAsDialog - }, - { - label: '导出(&E)...', - accelerator: 'CmdOrCtrl+E', - click: exportDialog - }, - { type: 'separator' }, - { - label: '自动保存', - type: 'checkbox', - checked: true, - click: autoSave - }, - { - label: '重选自动保存的目录(&R)', - accelerator: 'CmdOrCtrl+R', - click: setSavePath - }, - { type: 'separator' }, - { - label: '退出(&X)', - click: exitApp - } + { + label: i18n.__("miNewFile"), + accelerator: "CmdOrCtrl+N", + click: newDialog + }, + { + label: i18n.__("miOpenFile"), + accelerator: "CmdOrCtrl+O", + click: openDialog + }, + { type: "separator" }, + { + label: i18n.__("miOpenFolder"), + accelerator: "CmdOrCtrl+Shift+O", + click: openFileInFolder + }, + { + label: i18n.__("miOpenRecent"), + submenu: [ + { type: "separator" }, + { + id: 1, + label: i18n.__("miClearRecent"), + click: clearRecently + } + ] + }, + { type: "separator" }, + { + label: i18n.__("miSave"), + accelerator: "CmdOrCtrl+S", + click: saveDialog + }, + { + label: i18n.__("miSaveAs"), + accelerator: "CmdOrCtrl+Shift+S", + click: saveAsDialog + }, + { + label: i18n.__("miExport"), + accelerator: "CmdOrCtrl+E", + click: exportDialog + }, + { type: "separator" }, + { + label: i18n.__("miAutoSave"), + type: "checkbox", + checked: true, + click: autoSave + }, + { + label: i18n.__("miSavePath"), + accelerator: "CmdOrCtrl+R", + click: setSavePath + }, + { type: "separator" }, + { + label: i18n.__("miExit"), + click: exitApp + } ] -}, { - label: "编辑(&E)", + }, + { + label: i18n.__("mEdit"), submenu: [ - { - label: "撤销(&U)", - accelerator: 'CmdOrCtrl+Z', - click: undo, - selector: 'undo:' - }, - { - label: "恢复(&R)", - accelerator: 'CmdOrCtrl+Y', - click: redo, - selector: 'redo:' - }, - { type: 'separator' }, - { - label: "剪切(&T)", - accelerator: 'CmdOrCtrl+X', - selector: 'cut:', - role: 'cut' - }, - { - label: "复制(&C)", - accelerator: 'CmdOrCtrl+C', - selector: 'copy:', - role: 'copy' - }, - { - label: "粘贴(&P)", - accelerator: 'CmdOrCtrl+V', - selector: 'paste:', - role: 'paste' - } + { + label: i18n.__("miUndo"), + accelerator: "CmdOrCtrl+Z", + click: undo, + selector: "undo:" + }, + { + label: i18n.__("miRedo"), + accelerator: "CmdOrCtrl+Y", + click: redo, + selector: "redo:" + }, + { type: "separator" }, + { + label: i18n.__("miCut"), + accelerator: "CmdOrCtrl+X", + selector: "cut:", + role: "cut" + }, + { + label: i18n.__("miCopy"), + accelerator: "CmdOrCtrl+C", + selector: "copy:", + role: "copy" + }, + { + label: i18n.__("miPaste"), + accelerator: "CmdOrCtrl+V", + selector: "paste:", + role: "paste" + } ] -}, { - label: "窗口(&W)", + }, + { + label: i18n.__("mWindow"), submenu: [ - { - label: '最大化(&X)', - click: maxwin - }, - { - label: '最小化(&N)', - click: minwin - } + { + label: i18n.__("miMaxWin"), + click: maxwin + }, + { + label: i18n.__("miMinWin"), + click: minwin + } ] -}, { - label: "帮助(&H)", + }, + { + label: i18n.__("mHelp"), submenu: [ - { - label: '快捷键(&H)...', - accelerator: 'CmdOrCtrl+/', - click: shortcut - }, - { type: 'separator' }, - { label: "备份百度脑图到本地(&V)", click: license }, - { label: "检查更新...(&N)", click: checkVersion }, - { type: 'separator' }, - { label: "关于(&A)", click: about } + { + label: i18n.__("miShortcut"), + accelerator: "CmdOrCtrl+/", + click: shortcut + }, + { type: "separator" }, + { label: i18n.__("miBackup"), click: license }, + { label: i18n.__("miCheckVer"), click: checkVersion }, + { type: "separator" }, + { label: i18n.__("miAbout"), click: about } ] -}]; + } +]; var menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); diff --git a/src/js/open-file.js b/src/js/open-file.js index f8ef542..f1b01ef 100644 --- a/src/js/open-file.js +++ b/src/js/open-file.js @@ -5,7 +5,7 @@ body.ondrop = function (e) { e.preventDefault(); var file = e.dataTransfer.files[0]; if (!file.name.toLowerCase().endsWith(".km")) { - bootbox.alert("加载文件失败!只允许打开.km格式的文件!") + bootbox.alert(i18n.__("sLoadedError")) return false; } diff --git a/src/js/shortcut.js b/src/js/shortcut.js new file mode 100644 index 0000000..0fbacc0 --- /dev/null +++ b/src/js/shortcut.js @@ -0,0 +1,73 @@ +function shortcut() { + var shortcutKeys = [ + { + groupName: "节点操作", + groupItem: [ + { key: "Enter", desc: " 插入兄弟节点" }, + { key: "Tab, Insert", desc: " 插入子节点" }, + { key: "Shift + Tab", desc: " 插入父节点" }, + { key: "Delete", desc: " 删除节点" }, + { key: "Up, Down, Left, Right", desc: " 节点导航" }, + { key: "Alt + Up, Down", desc: " 向上/向下调整顺序" }, + { key: "/", desc: " 展开/收起节点" }, + { key: "F2", desc: " 编辑节点" }, + { key: "Shift + Enter", desc: " 文本换行" }, + { key: "Ctrl + A", desc: " 全选节点" }, + { key: "Ctrl + C", desc: " 复制节点" }, + { key: "Ctrl + X", desc: " 剪切节点" }, + { key: "Ctrl + V", desc: " 粘贴节点" }, + { key: "Ctrl + B", desc: " 加粗" }, + { key: "Ctrl + I", desc: " 斜体" }, + { key: "Ctrl + F", desc: " 查找节点" } + ] + }, + { + groupName: "视野控制", + groupItem: [ + //{ key:"Ctrl + ESC",desc:" 全屏切换"}, + { key: "Alt + 拖动, 右键拖动", desc: " 拖动视野" }, + { key: "滚轮, 触摸板", desc: " 移动视野" }, + //{ key:"Ctrl + Up, Down, Left, Right",desc:" 视野导航"}, + { key: "空白处双击, Ctrl + Enter", desc: " 居中根节点" }, + { key: "Ctrl + +, -", desc: " 放大/缩小视野" } + ] + }, + { + groupName: "文件操作", + groupItem: [ + { key: "Ctrl + O", desc: " 打开" }, + { key: "Ctrl + S", desc: " 保存" }, + { key: "Ctrl + Shift + S", desc: " 另存为" } + // { key: "Ctrl + Alt + S", desc: " 分享" } + ] + }, + { + groupName: "布局", + groupItem: [{ key: "Ctrl + Shift + L", desc: " 整理布局" }] + }, + { + groupName: "后悔药", + groupItem: [ + { key: "Ctrl + Z", desc: " 撤销" }, + { key: "Ctrl + Y", desc: " 重做" } + ] + } + ]; + + var text = ""; + for (var i = 0; i < shortcutKeys.length; i++) { + var group = shortcutKeys[i]; + text += `\n` + group.groupName + `\n`; + for (var j = 0; j < group.groupItem.length; j++) { + var item = group.groupItem[j]; + text += ` ` + item.desc + ` ` + item.key + `\n`; + } + } + + dialog.showMessageBox({ + type: "none", + title: "快捷键", + message: text, + buttons: ["OK"] + }); +} diff --git a/version.js b/version.js index cc43a3c..c1e4470 100644 --- a/version.js +++ b/version.js @@ -1 +1 @@ -exports.version = [2, 1, 1, 399]; \ No newline at end of file +exports.version = [3, 0, 0, 426]; \ No newline at end of file