diff --git a/src/background.js b/src/background.js index 6dd2c59..a53ccc7 100644 --- a/src/background.js +++ b/src/background.js @@ -13,6 +13,8 @@ const {yModem} = require('./ymodem') const path = require('path') const fs = require('fs') const fsPromises = fs.promises +const Store = require('electron-store') +const store = new Store() let appName = "SenseCAP Node Configuration Tool" app.name = appName @@ -26,6 +28,7 @@ autoUpdater.logger.transports.file.level = isDevelopment ? "debug" : "info" // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let win +let sysLocale let serialPorts = [] let selectedSerialPort @@ -39,7 +42,7 @@ let autoUpdateTimeHandler = null * The Menu's locale only follows the system, the user selection from the GUI doesn't affect */ async function translateMenu() { - let sysLocale = process.env.LOCALE || app.getLocale() + sysLocale = store.get('chosenLocale') || process.env.LOCALE || app.getLocale() logger.info('the sys locale:', sysLocale) await i18next.init({ @@ -415,3 +418,13 @@ ipcMain.on('select-file', async (event, selPort) => { }) +// locale +ipcMain.on('locale-req', (event) => { + event.reply('locale-resp', sysLocale) +}) + +ipcMain.on('locale-change', (event, arg) => { + i18next.changeLanguage(arg) + translateMenu() +}) + diff --git a/src/locale/common.js b/src/locale/common.js new file mode 100644 index 0000000..b3635a0 --- /dev/null +++ b/src/locale/common.js @@ -0,0 +1,127 @@ +export default { + "en": { + //通用词组 + "Yes": "Yes", + "No": "No", + "Frequency": "Frequency", + "SF": "SF", + "High": "High", + "Low": "Low", + "Device Class": "Device Class", + "Short Address": "Short Address", + "Channel Count": "Channel Count", + "Upload Interval": "Upload Interval", + "RF Priority": "RF Priority", + "Battery": "Battery", + "Last RSSI": "Last RSSI", + "Last Message Time": "Last Message Time", + "Operations": "Operations", + "Always-on": "Always-on", + "Sleep": "Sleep", + "minutes": "minutes", + "Total": "Total", + "Per Page": "Per Page", + "Channel": "Channel", + "Measurement": "Measurement", + "Value": "Value", + "Data Collect Time": "Data Collect Time", + "Data Upload Time": "Data Upload Time", + "Downlink Cmd ID": "Downlink Cmd ID", + "Content": "Content", + "Cmd Arrival Time": "Cmd Arrival Time", + "Cmd Ack Time": "Cmd Ack Time", + "Status": "Status", + "Username": "Username", + "Password": "Password", + //按钮 + "Add": "Add", + "Apply": "Apply", + "Save": "Save", + "Close": "Close", + "Cancel": "Cancel", + "OK": "OK", + "Live Refresh": "Live Refresh", + "Remove": "Remove", + "Settings": "Settings", + "Import": "Import", + "Export": "Export", + "Backup": "Backup", + "Restore": "Restore", + "Filter": "Filter", + "Search": "Search", + "Check": "Check", + "Update": "Update", + //对话框 + "Please confirm": "Please confirm", + "Error: ": "Error: ", + "MQTT request timeout": "LoRa network server does not respond", + //规则 + "Required.": "Required.", + "Must be equal or greater than 5.": "Must be equal or greater than 5.", + "Must be integer.": "Must be integer.", + "At least 8 characters": "At least 8 characters" + }, + "zh": { + //通用词组 + "Yes": "是", + "No": "否", + "Frequency": "频率", + "SF": "扩频因子", + "High": "高", + "Low": "低", + "Device Class": "设备类型", + "Short Address": "短地址", + "Channel Count": "通道数量", + "Upload Interval": "上传周期", + "RF Priority": "射频优先级", + "Battery": "电量", + "Last RSSI": "最新信号强度", + "Last Message Time": "最新消息时间", + "Operations": "操作", + "Always-on": "常电型", + "Sleep": "睡眠型", + "minutes": "分", + "Total": "总共", + "Per Page": "条每页", + "Time": "时间", + "Channel": "通道", + "Measurement": "测量", + "Value": "值", + "Data Collect Time": "数据采集时间", + "Data Upload Time": "数据上云时间", + "Downlink Cmd ID": "下行命令ID", + "Content": "内容", + "Cmd Arrival Time": "命令到达时间", + "Cmd Ack Time": "命令应答时间", + "Status": "下行状态", + "Username": "用户名", + "Password": "密码", + //按钮 + "Add": "添加", + "Apply": "应用", + "Save": "保存", + "Close": "关闭", + "Cancel": "取消", + "OK": "确定", + "Live Refresh": "实时刷新", + "Remove": "移除", + "Settings": "设置", + "Import": "导入", + "Export": "导出", + "Backup": "备份", + "Restore": "还原", + "Filter": "过滤", + "Search": "搜索", + "Check": "检查版本", + "Update": "立即更新", + //对话框 + "Please confirm": "请确认", + "Error: ": "发生了错误:", + "MQTT request timeout": "LoRa网络服务暂无响应", + //规则 + "Required.": "必填", + "Must be equal or greater than 5.": "必须大于等于5", + "Must be integer.": "必须是整数", + "At least 8 characters": "至少8个字符" + } + } diff --git a/src/main.js b/src/main.js index b0458e4..f8bbed5 100644 --- a/src/main.js +++ b/src/main.js @@ -2,9 +2,11 @@ import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' -import vuetify from './plugins/vuetify'; +import vuetify from './plugins/vuetify' import 'roboto-fontface/css/roboto/roboto-fontface.css' import '@mdi/font/css/materialdesignicons.css' +import i18n from './plugins/i18n' +import 'flag-icon-css/css/flag-icon.css' Vue.config.productionTip = false @@ -12,5 +14,6 @@ new Vue({ router, store, vuetify, + i18n, render: h => h(App) }).$mount('#app') diff --git a/src/plugins/i18n.js b/src/plugins/i18n.js new file mode 100644 index 0000000..95571c7 --- /dev/null +++ b/src/plugins/i18n.js @@ -0,0 +1,38 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' +import commonMessages from '../locale/common' +const Store = require('electron-store') +const store = new Store() +const { ipcRenderer } = require('electron') + +Vue.use(VueI18n) + +let i18n = new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + silentFallbackWarn: true, + silentTranslationWarn: true, + messages: commonMessages, +}) + +function formatLocale(locale) { + if (locale.includes('en')) return 'en' + else if (locale.includes('zh')) return 'zh' + else if (locale.includes('cn')) return 'zh' + return 'en' +} + +//query stored locale +let chosenLocale = store.get('chosenLocale') +if (!chosenLocale) { + ipcRenderer.send('locale-req') + ipcRenderer.on('locale-resp', (event, arg) => { + chosenLocale = arg + + i18n.locale = formatLocale(chosenLocale) + }) +} else { + i18n.locale = formatLocale(chosenLocale) +} + +export default i18n \ No newline at end of file diff --git a/src/views/Home.vue b/src/views/Home.vue index dec240c..bcaa237 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,3 +1,30 @@ + +{ + "en": { + "end": "end" + }, + "zh": { + "Serial Port": "串口", + "Device Type": "设备类型", + "Device EUI": "设备EUI", + "Data Interval": "上报周期", + "Hardware Version": "硬件版本", + "Software Version": "软件版本", + "Read": "读取", + "Write": "写入", + "Update Fw": "更新固件", + "Connect": "连接", + "Disconnect": "断开", + + "Must between [5, 43200]": "必须在[5, 43200]范围内", + "Must between [5, 720]": "必须在[5, 720]范围内", + "Invalid LoRaWAN EUI (16 chars)": "无效的LoRaWAN EUI (16字符)", + "Invalid LoRaPP EUI (32 chars)": "无效的LoRaPP EUI (32字符)", + + "end": "结束" + } +} +