Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Implement i18n for electron wrapper menu - Closes #768 #797

Merged
merged 25 commits into from
Oct 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7d32a9f
Add json storage to store selected language
reyraa Oct 13, 2017
7515df4
Create a utility to receive the default/stored language from electron
reyraa Oct 13, 2017
35ea643
Initiate the apiLocale listener
reyraa Oct 13, 2017
da90a94
Use a generic t function to translate menu labels
reyraa Oct 13, 2017
ef091e2
Add listeners amd event emitters to comminicate the locale with the c…
reyraa Oct 13, 2017
bbee293
Add electron app translation scanning to i18n-scanner.js
yasharAyari Oct 15, 2017
9331bda
Fix a bug in menu.js
yasharAyari Oct 15, 2017
13b8a3e
Add i18n to main.js and use it in main.js
yasharAyari Oct 15, 2017
06b4d59
Add electron menu translation strings to commmon.json
yasharAyari Oct 15, 2017
c248fe8
Create i18next confing for electron
yasharAyari Oct 15, 2017
482ee32
Create language constant in app folder
yasharAyari Oct 15, 2017
d117421
Add locales folder to copy-files script
yasharAyari Oct 15, 2017
a1bcac1
Fix some bugs in main.js and i18n.js in app folder
yasharAyari Oct 15, 2017
ebf226e
Merge branch 'development' into '768-electron-menu-i18n'
yasharAyari Oct 16, 2017
95275d2
Fix a bug in languages.js
yasharAyari Oct 16, 2017
0f907ec
Store user selected language in a json file
yasharAyari Oct 17, 2017
e94a298
Update electron-json-file in package.json
yasharAyari Oct 17, 2017
8dcada9
Merge branch 'development' into 768-electron-menu-i18n
yasharAyari Oct 17, 2017
42e6e12
Fix a bug in common.json
yasharAyari Oct 17, 2017
c3175f8
Fix a bug in menu.js
yasharAyari Oct 17, 2017
e690f71
Fix a bug in common.json and electron menu strings to it
yasharAyari Oct 17, 2017
743539a
Run npm clean and copy-files before npm run eslint in genkinsfile
yasharAyari Oct 17, 2017
925b1bd
Fix a bug in menu.json
yasharAyari Oct 17, 2017
e8d0f05
Change some translation strings in common.json
yasharAyari Oct 17, 2017
c44b476
Fix a bug in ipcLocale test file
yasharAyari Oct 17, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ node('lisk-nano') {
stage ('Run Eslint') {
try {
ansiColor('xterm') {
sh 'npm run --silent eslint'
sh 'npm run --silent clean && npm run --silent copy-files && npm run --silent eslint'
}
} catch (err) {
echo "Error: ${err}"
Expand Down
26 changes: 26 additions & 0 deletions app/src/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import i18n from 'i18next'; // eslint-disable-line import/no-extraneous-dependencies
import languages from './languages';

const resources = Object.keys(languages).reduce((accumulator, key) => {
accumulator[key] = {
common: languages[key].common,
};
return accumulator;
}, {});

i18n
.init({
fallbackLng: 'en',
resources,
lang: 'en',
ns: ['common'],
defaultNS: 'common',
saveMissing: true,
debug: false,
}, (err, t) => {
t('key');
// initialized and ready to go!
console.log(`Current language used: ${i18n.language}`); //eslint-disable-line
});

export default i18n;
12 changes: 12 additions & 0 deletions app/src/languages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const languages = {
en: {
name: 'English',
common: require('../build/locales/en/common.json'),
},
de: {
name: 'Deutsch',
common: require('../build/locales/de/common.json'),
},
};

export default languages;
46 changes: 45 additions & 1 deletion app/src/main.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import electron from 'electron'; // eslint-disable-line import/no-extraneous-dependencies
import path from 'path';
import storage from 'electron-json-storage'; // eslint-disable-line import/no-extraneous-dependencies
import i18n from './i18n';
import buildMenu from './menu';

const { app, BrowserWindow, Menu, ipcMain } = electron;

let win;
let isUILoaded = false;
let eventStack = [];
// @todo change en with the detected lang
const defaultLng = 'en';
let lang;

const copyright = `Copyright © 2016 - ${new Date().getFullYear()} Lisk Foundation`;
const protocolName = 'lisk';
Expand All @@ -19,7 +24,33 @@ const sendUrlToRouter = (url) => {
}
};

/**
* Sends an event to client application
* @param {String} locale - the 2 letter name of the local
*/
const sendDetectedLang = (locale) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sendDetectedLang looks very similar tosendUrlToRouter. The common pattern could be abstracted into a function, e.g.: sendEvent(eventName, data)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need event in sendDetectedLang but we don't need it in sendUrlToRouter

if (isUILoaded && win && win.webContents) {
win.webContents.send('detectedLocale', locale);
} else {
eventStack.push({ event: 'detectedLocale', value: locale });
}
};

// read config data from JSON file
storage.get('config', (error, data) => {
if (error) throw error;
lang = data.lang;
sendDetectedLang(lang);
});

function createWindow() {
// set language of the react app
if (lang) {
sendDetectedLang(lang);
} else {
sendDetectedLang(defaultLng);
}

const { width, height } = electron.screen.getPrimaryDisplay().workAreaSize;
win = new BrowserWindow({
width: width > 2000 ? Math.floor(width * 0.5) : width - 250,
Expand All @@ -39,7 +70,7 @@ function createWindow() {
sendUrlToRouter(process.argv.slice(1));
}

Menu.setApplicationMenu(buildMenu(app, copyright));
Menu.setApplicationMenu(buildMenu(app, copyright, i18n));
win.loadURL(`file://${__dirname}/index.html`);

win.on('closed', () => { win = null; });
Expand Down Expand Up @@ -138,3 +169,16 @@ ipcMain.on('proxyCredentialsEntered', (event, username, password) => {
global.myTempFunction(username, password);
});

ipcMain.on('set-locale', (event, locale) => {
const langCode = locale.substr(0, 2);
if (langCode) {
lang = langCode;
i18n.changeLanguage(langCode);
// write selected lang on JSON file
storage.set('config', { lang: langCode }, (error) => {
if (error) throw error;
});
Menu.setApplicationMenu(buildMenu(app, copyright, i18n));
event.returnValue = 'Rebuilt electron menu.';
}
});
193 changes: 102 additions & 91 deletions app/src/menu.js
Original file line number Diff line number Diff line change
@@ -1,124 +1,135 @@
import electron from 'electron'; // eslint-disable-line import/no-extraneous-dependencies
const electron = require('electron'); // eslint-disable-line import/no-extraneous-dependencies

const { Menu } = electron;

const template = [
{
label: 'Edit',
submenu: [
{
role: 'undo',
},
{
role: 'redo',
},
{
type: 'separator',
},
{
role: 'cut',
},
{
role: 'copy',
},
{
role: 'paste',
},
{
role: 'selectall',
},
],
},
{
label: 'View',
submenu: [
{
role: 'reload',
},
{
role: 'togglefullscreen',
},
],
},
{
label: 'Window',
submenu: [
{
role: 'minimize',
},
],
},
{
label: 'Help',
submenu: [
{
label: 'Lisk Website',
click() {
electron.shell.openExternal('https://lisk.io');
const buildTemplate = i18n =>
[
{
label: i18n.t('Edit'),
submenu: [
{
role: 'undo',
label: i18n.t('Undo'),
},
},
{
label: 'Lisk Chat',
click() {
electron.shell.openExternal('https://lisk.chat');
{
role: 'redo',
label: i18n.t('Redo'),
},
},
{
label: 'Lisk Explorer',
click() {
electron.shell.openExternal('https://explorer.lisk.io');
{
type: 'separator',
},
},
{
label: 'Lisk Forum',
click() {
electron.shell.openExternal('https://forum.lisk.io');
{
role: 'cut',
label: i18n.t('Cut'),
},
},
{
type: 'separator',
},
{
label: 'Report Issue...',
click() {
electron.shell.openExternal('https://lisk.zendesk.com/hc/en-us/requests/new');
{
role: 'copy',
label: i18n.t('Copy'),
},
},
{
label: 'What\'s New...',
click() {
electron.shell.openExternal('https://github.com/LiskHQ/lisk-nano/releases');
{
role: 'paste',
label: i18n.t('Paste'),
},
},
],
},
];
{
role: 'selectall',
label: i18n.t('Select all'),
},
],
},
{
label: i18n.t('View'),
submenu: [
{
role: 'reload',
label: i18n.t('Reload'),
},
{
role: 'togglefullscreen',
label: i18n.t('Toggle full screen'),
},
],
},
{
label: i18n.t('Window'),
submenu: [
{
role: 'minimize',
label: i18n.t('Minimize'),
},
],
},
{
label: i18n.t('Help'),
submenu: [
{
label: i18n.t('Lisk Website'),
click() {
electron.shell.openExternal('https://lisk.io');
},
},
{
label: i18n.t('Lisk Chat'),
click() {
electron.shell.openExternal('https://lisk.chat');
},
},
{
label: i18n.t('Lisk Explorer'),
click() {
electron.shell.openExternal('https://explorer.lisk.io');
},
},
{
label: i18n.t('Lisk Forum'),
click() {
electron.shell.openExternal('https://forum.lisk.io');
},
},
{
type: 'separator',
},
{
label: i18n.t('Report Issue...'),
click() {
electron.shell.openExternal('https://lisk.zendesk.com/hc/en-us/requests/new');
},
},
{
label: i18n.t('What\'s New...'),
click() {
electron.shell.openExternal('https://github.com/LiskHQ/lisk-nano/releases');
},
},
],
},
];

export default (app, copyright) => {
module.exports = (app, copyright, i18n) => {
const template = buildTemplate(i18n);
if (process.platform === 'darwin') {
const name = app.getName();
template.unshift({
label: name,
submenu: [
{
role: 'about',
label: 'About',
label: i18n.t('About'),
},
{
role: 'quit',
label: 'Quit',
label: i18n.t('Quit'),
},
],
});
} else {
template[template.length - 1].submenu.push({
label: 'About',
label: i18n.t('About'),
click(item, focusedWindow) {
if (focusedWindow) {
const options = {
buttons: ['OK'],
icon: `${__dirname}/assets/lisk.png`,
message: `Lisk Nano\nVersion ${app.getVersion()}\n${copyright}`,
message: `${i18n.t('Lisk Nano')} \n ${i18n.t('Version')} ${app.getVersion()}\n${copyright}`,
};
electron.dialog.showMessageBox(focusedWindow, options, () => {});
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dist:win": "build --win --ia32 --x64",
"dist:mac": "build --mac",
"dist:linux": "build --linux --ia32 --x64 --armv7l",
"copy-files": "mkdir app/build && cp -r ./src/index.html ./src/assets ./app/build",
"copy-files": "mkdir app/build && cp -r ./src/index.html ./src/assets ./src/locales ./app/build",
"clean": "del app/build -f",
"eslint": "eslint ./src/ ./app/src/ ./app/config/ ./features/",
"storybook": "start-storybook -p 6006 -s ./src/",
Expand Down Expand Up @@ -81,6 +81,7 @@
"del-cli": "1.1.0",
"electron": "1.7.8",
"electron-builder": "19.32.2",
"electron-json-storage": "^3.2.0",
"enzyme": "2.9.1",
"eslint": "4.8.0",
"eslint-config-airbnb": "15.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n-scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const customHandler = function (key, options) {
};

const files = glob.sync('./src/**/*.js', {});
files.forEach((file) => {
const electronFiles = glob.sync('./app/src/**/*.js', {});
[...files, ...electronFiles].forEach((file) => {
const content = fs.readFileSync(file, 'utf-8');
parser.parseFuncFromString(content, { list: translationFunctionNames }, customHandler);
});
Expand Down
Loading