mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
ELECTRON-519: support Japanese localization for menus, dialogs and windows (#401)
- add basic localisation implementation for menu items - add more strings to support localisation on menus - add more strings to support localisation on menus - add all menu items for localisation - refactor i18n code - Add localization for screen picker, basic auth and notification settings child windows - Add localization bridge - add i18n support to more strings - update translations - add events to change language and redo menu template - move config update logic to windowMgr - fix linting issues and refactor - add snipping tool messages
This commit is contained in:
committed by
GitHub
parent
fd39d680a0
commit
a26a1d609c
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,4 +31,5 @@ installer/win/Symphony-x86-cache
|
||||
installer/win/Symphony-x86-SetupFiles
|
||||
package-lock.json
|
||||
library
|
||||
*.log
|
||||
*.log
|
||||
js/translation/*_missing.json
|
||||
@@ -8,6 +8,7 @@ const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const buildNumber = require('../../package.json').buildNumber;
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
let aboutWindow;
|
||||
|
||||
@@ -90,8 +91,8 @@ function openAboutWindow(windowName) {
|
||||
aboutWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash.'),
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Authentication Request</title>
|
||||
<title data-i18n-text="Authentication Request"></title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.container {
|
||||
@@ -62,20 +63,20 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<span>Please provide your login credentials for:</span>
|
||||
<span id="hostname" class="hostname">hostname</span>
|
||||
<span id="credentialsError" class="credentials-error">Invalid user name/password</span>
|
||||
<span data-i18n-text="Please provide your login credentials for:"></span>
|
||||
<span id="hostname" class="hostname" data-i18n-text="hostname"></span>
|
||||
<span id="credentialsError" class="credentials-error" data-i18n-text="Invalid user name/password"></span>
|
||||
<form id="basicAuth" name="Basic Auth" action="Login">
|
||||
<table class="form">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>User name:</td>
|
||||
<td id="username-text" data-i18n-text="User name:"></td>
|
||||
<td>
|
||||
<input id="username" name="username" title="Username" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td id="password-text" data-i18n-text="Password:"></td>
|
||||
<td>
|
||||
<input id="password" type="password" title="Password" required>
|
||||
</td>
|
||||
@@ -84,10 +85,10 @@
|
||||
</table>
|
||||
<div class="footer">
|
||||
<div class="button-container">
|
||||
<button type="submit" id="login">Log In</button>
|
||||
<button type="submit" id="login" data-i18n-text="Log In"></button>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button type="button" id="cancel">Cancel</button>
|
||||
<button type="button" id="cancel" data-i18n-text="Cancel"></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -9,6 +9,7 @@ const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const { isMac } = require('../utils/misc');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
let basicAuthWindow;
|
||||
|
||||
@@ -96,6 +97,8 @@ function openBasicAuthWindow(windowName, hostname, isValidCredentials, clearSett
|
||||
});
|
||||
|
||||
basicAuthWindow.webContents.on('did-finish-load', () => {
|
||||
const basicAuthContent = i18n.getMessageFor('BasicAuth');
|
||||
basicAuthWindow.webContents.send('i18n-basic-auth', basicAuthContent);
|
||||
// initialize crash reporter
|
||||
initCrashReporterMain({ process: 'basic auth window' });
|
||||
initCrashReporterRenderer(basicAuthWindow, { process: 'render | basic auth window' });
|
||||
@@ -106,8 +109,8 @@ function openBasicAuthWindow(windowName, hostname, isValidCredentials, clearSett
|
||||
basicAuthWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash.'),
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
|
||||
@@ -68,4 +68,16 @@ ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on('i18n-basic-auth', (event, content) => {
|
||||
if (content && typeof content === 'object') {
|
||||
const i18nNodes = document.querySelectorAll('[data-i18n-text]');
|
||||
|
||||
for (let node of i18nNodes) {
|
||||
if (node.attributes['data-i18n-text'] && node.attributes['data-i18n-text'].value) {
|
||||
node.innerText = content[node.attributes['data-i18n-text'].value] || node.attributes['data-i18n-text'].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -9,6 +9,7 @@ const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const { isMac, isWindowsOS } = require('./../utils/misc.js');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
let screenPickerWindow;
|
||||
let preloadWindow;
|
||||
@@ -92,6 +93,8 @@ function openScreenPickerWindow(eventSender, sources, id) {
|
||||
});
|
||||
|
||||
screenPickerWindow.webContents.on('did-finish-load', () => {
|
||||
const screenPickerContent = i18n.getMessageFor('ScreenPicker');
|
||||
screenPickerWindow.webContents.send('i18n-screen-picker', screenPickerContent);
|
||||
// initialize crash reporter
|
||||
initCrashReporterMain({ process: 'desktop capture window' });
|
||||
initCrashReporterRenderer(screenPickerWindow, { process: 'render | desktop capture window' });
|
||||
@@ -101,8 +104,8 @@ function openScreenPickerWindow(eventSender, sources, id) {
|
||||
screenPickerWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash.'),
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ const keyCodeEnum = Object.freeze({
|
||||
let availableSources;
|
||||
let selectedSource;
|
||||
let currentIndex = -1;
|
||||
let localizedContent;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
renderDom();
|
||||
@@ -49,11 +50,15 @@ function renderDom() {
|
||||
}, false);
|
||||
|
||||
screenTab.addEventListener('click', () => {
|
||||
updateShareButtonText('Select Screen');
|
||||
updateShareButtonText(localizedContent && localizedContent[ 'Select Screen' ] ?
|
||||
localizedContent[ 'Select Screen' ] :
|
||||
'Select Screen');
|
||||
}, false);
|
||||
|
||||
applicationTab.addEventListener('click', () => {
|
||||
updateShareButtonText('Select Application');
|
||||
updateShareButtonText(localizedContent && localizedContent[ 'Select Application' ] ?
|
||||
localizedContent[ 'Select Application' ] :
|
||||
'Select Application');
|
||||
}, false);
|
||||
|
||||
document.addEventListener('keyup', handleKeyUpPress.bind(this), true);
|
||||
@@ -164,7 +169,7 @@ function updateUI(source, itemContainer) {
|
||||
|
||||
highlightSelectedSource();
|
||||
itemContainer.classList.add('selected');
|
||||
shareButton.innerText = 'Share'
|
||||
shareButton.innerText = localizedContent && localizedContent.Share ? localizedContent.Share : 'Share';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,4 +276,17 @@ ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on('i18n-screen-picker', (event, content) => {
|
||||
localizedContent = content;
|
||||
if (content && typeof content === 'object') {
|
||||
const i18nNodes = document.querySelectorAll('[data-i18n-text]');
|
||||
|
||||
for (let node of i18nNodes) {
|
||||
if (node.attributes['data-i18n-text'] && node.attributes['data-i18n-text'].value) {
|
||||
node.innerText = content[node.attributes['data-i18n-text'].value] || node.attributes['data-i18n-text'].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Screen Picker</title>
|
||||
<title data-i18n-text="Screen Picker"></title>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
@@ -211,7 +211,7 @@
|
||||
<body>
|
||||
<div class="content">
|
||||
<div class="custom-window-title">
|
||||
<span>Choose what you'd like to share</span>
|
||||
<span data-i18n-text="Choose what you'd like to share"></span>
|
||||
<div id="x-button">
|
||||
<div class="content-button">
|
||||
<i>
|
||||
@@ -223,13 +223,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="error-content">
|
||||
<span id="error-message">No screens or applications are currently available.</span>
|
||||
<span id="error-message" data-i18n-text="No screens or applications are currently available."></span>
|
||||
</div>
|
||||
<div id="main-content">
|
||||
<input id="screen-tab" type="radio" name="tabs" checked>
|
||||
<label id="screens" for="screen-tab" class="hidden">Screens</label>
|
||||
<label id="screens" for="screen-tab" class="hidden" data-i18n-text="Screens"></label>
|
||||
<input id="application-tab" type="radio" name="tabs">
|
||||
<label id="applications" for="application-tab" class="hidden">Applications</label>
|
||||
<label id="applications" for="application-tab" class="hidden" data-i18n-text="Applications"></label>
|
||||
<section id="screen-contents">
|
||||
</section>
|
||||
<section id="application-contents">
|
||||
@@ -237,8 +237,8 @@
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<button id="cancel" class="cancel-button">Cancel</button>
|
||||
<button id="share" class="share-button-disable">Select Screen</button>
|
||||
<button id="cancel" class="cancel-button" data-i18n-text="Cancel"></button>
|
||||
<button id="share" class="share-button-disable" data-i18n-text="Select Screen"></button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ const electron = require('electron');
|
||||
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
let ignoreAllCertErrors = false;
|
||||
|
||||
@@ -33,8 +34,8 @@ electron.app.on('certificate-error', function(event, webContents, url, error,
|
||||
defaultId: 1,
|
||||
cancelId: 1,
|
||||
noLink: true,
|
||||
title: 'Certificate Error',
|
||||
message: 'Certificate Error: ' + error + '\nURL: ' + url,
|
||||
title: i18n.getMessageFor('Certificate Error'),
|
||||
message: i18n.getMessageFor('Certificate Error') + `: ${error}\nURL: ${url}`,
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
@@ -4,6 +4,7 @@ const electron = require('electron');
|
||||
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
/**
|
||||
* Show dialog pinned to given window when loading error occurs
|
||||
@@ -17,9 +18,9 @@ const logLevels = require('../enums/logLevels.js');
|
||||
function showLoadFailure(win, url, errorDesc, errorCode, retryCallback, showDialog) {
|
||||
let msg;
|
||||
if (url) {
|
||||
msg = 'Error loading URL:\n' + url;
|
||||
msg = i18n.getMessageFor('Error loading URL') + `:\n${url}`;
|
||||
} else {
|
||||
msg = 'Error loading window';
|
||||
msg = i18n.getMessageFor('Error loading window');
|
||||
}
|
||||
if (errorDesc) {
|
||||
msg += '\n\n' + errorDesc;
|
||||
@@ -35,7 +36,7 @@ function showLoadFailure(win, url, errorDesc, errorCode, retryCallback, showDial
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
noLink: true,
|
||||
title: 'Loading Error',
|
||||
title: i18n.getMessageFor('Loading Error'),
|
||||
message: msg
|
||||
}, response);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ const cmds = keyMirror({
|
||||
openScreenPickerWindow: null,
|
||||
popupMenu: null,
|
||||
optimizeMemoryConsumption: null,
|
||||
setIsInMeeting: null
|
||||
setIsInMeeting: null,
|
||||
setLocale: null,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -142,12 +142,13 @@ electron.ipcMain.on(apiName, (event, arg) => {
|
||||
openScreenPickerWindow(event.sender, arg.sources, arg.id);
|
||||
}
|
||||
break;
|
||||
case apiCmds.popupMenu:
|
||||
var browserWin = electron.BrowserWindow.fromWebContents(event.sender);
|
||||
case apiCmds.popupMenu: {
|
||||
let browserWin = electron.BrowserWindow.fromWebContents(event.sender);
|
||||
if (browserWin && !browserWin.isDestroyed()) {
|
||||
windowMgr.getMenu().popup(browserWin, { x: 20, y: 15, async: true });
|
||||
windowMgr.getMenu().popup(browserWin, {x: 20, y: 15, async: true});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case apiCmds.optimizeMemoryConsumption:
|
||||
if (typeof arg.memory === 'object' && typeof arg.cpuUsage === 'object' && typeof arg.memory.workingSetSize === 'number') {
|
||||
optimizeMemory(arg.memory, arg.cpuUsage);
|
||||
@@ -158,6 +159,11 @@ electron.ipcMain.on(apiName, (event, arg) => {
|
||||
setIsInMeeting(arg.isInMeeting);
|
||||
}
|
||||
break;
|
||||
case apiCmds.setLocale:
|
||||
if (typeof arg.locale === 'string') {
|
||||
eventEmitter.emit('language-changed', { language: arg.locale });
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
const fs = require('fs');
|
||||
const { updateConfigField, getMultipleConfigField } = require('../config.js');
|
||||
const AutoLaunch = require('auto-launch');
|
||||
const electron = require('electron');
|
||||
|
||||
const { updateConfigField, getMultipleConfigField } = require('../config.js');
|
||||
const { isMac, isWindowsOS, isWindows10 } = require('../utils/misc.js');
|
||||
const archiveHandler = require('../utils/archiveHandler');
|
||||
const log = require('../log.js');
|
||||
@@ -11,6 +12,7 @@ const logLevels = require('../enums/logLevels.js');
|
||||
const eventEmitter = require('../eventEmitter');
|
||||
const aboutApp = require('../aboutApp');
|
||||
const titleBarStyles = require('../enums/titleBarStyles');
|
||||
const i18n = require('../translation/i18n');
|
||||
|
||||
const configFields = [
|
||||
'minimizeOnClose',
|
||||
@@ -62,197 +64,228 @@ if (isMac) {
|
||||
});
|
||||
}
|
||||
|
||||
const template = [{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
buildMenuItem('undo'),
|
||||
buildMenuItem('redo'),
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('cut'),
|
||||
buildMenuItem('copy'),
|
||||
buildMenuItem('paste'),
|
||||
buildMenuItem('pasteandmatchstyle'),
|
||||
buildMenuItem('delete'),
|
||||
buildMenuItem('selectall')
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.reload();
|
||||
}
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('resetzoom'),
|
||||
buildMenuItem('zoomin'),
|
||||
buildMenuItem('zoomout'),
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('togglefullscreen'),
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
submenu: [
|
||||
buildMenuItem('minimize'),
|
||||
buildMenuItem('close'),
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
submenu:
|
||||
[
|
||||
{
|
||||
label: 'Symphony Help',
|
||||
click() { electron.shell.openExternal('https://support.symphony.com'); }
|
||||
},
|
||||
{
|
||||
label: 'Learn More',
|
||||
click() { electron.shell.openExternal('https://www.symphony.com'); }
|
||||
},
|
||||
{
|
||||
label: 'Troubleshooting',
|
||||
submenu: [
|
||||
{
|
||||
label: isMac ? 'Show Logs in Finder' : 'Show Logs in Explorer',
|
||||
click(item, focusedWindow) {
|
||||
|
||||
const FILE_EXTENSIONS = [ '.log' ];
|
||||
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
|
||||
const WINDOWS_LOGS_PATH = '\\AppData\\Roaming\\Symphony\\logs';
|
||||
|
||||
let logsPath = isMac ? MAC_LOGS_PATH : WINDOWS_LOGS_PATH;
|
||||
let source = electron.app.getPath('home') + logsPath;
|
||||
|
||||
if (!fs.existsSync(source) && focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title: 'Failed!', message: 'No logs are available to share'});
|
||||
return;
|
||||
}
|
||||
|
||||
let destPath = isMac ? '/logs_symphony_' : '\\logs_symphony_';
|
||||
let timestamp = new Date().getTime();
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title: 'Failed!', message: `Unable to generate logs due to -> ${err}`});
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
label: isMac ? 'Show crash dump in Finder' : 'Show crash dump in Explorer',
|
||||
click(item, focusedWindow) {
|
||||
const FILE_EXTENSIONS = isMac ? [ '.dmp' ] : [ '.dmp', '.txt' ];
|
||||
const crashesDirectory = electron.crashReporter.getCrashesDirectory();
|
||||
let source = isMac ? crashesDirectory + '/completed' : crashesDirectory;
|
||||
|
||||
// TODO: Add support to get diagnostic reports from ~/Library/Logs/DiagnosticReports
|
||||
if (!fs.existsSync(source) || fs.readdirSync(source).length === 0 && focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title: 'Failed!', message: 'No crashes available to share'});
|
||||
return;
|
||||
}
|
||||
|
||||
let destPath = isMac ? '/crashes_symphony_' : '\\crashes_symphony_';
|
||||
let timestamp = new Date().getTime();
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title: 'Failed!', message: `Unable to generate crash reports due to -> ${err}`});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
function getTemplate(app) {
|
||||
|
||||
const template = [{
|
||||
label: i18n.getMessageFor('Edit'),
|
||||
submenu: [
|
||||
buildMenuItem('undo', i18n.getMessageFor('Undo')),
|
||||
buildMenuItem('redo', i18n.getMessageFor('Redo')),
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('cut', i18n.getMessageFor('Cut')),
|
||||
buildMenuItem('copy', i18n.getMessageFor('Copy')),
|
||||
buildMenuItem('paste', i18n.getMessageFor('Paste')),
|
||||
buildMenuItem('pasteandmatchstyle', i18n.getMessageFor('Paste and Match Style')),
|
||||
buildMenuItem('delete', i18n.getMessageFor('Delete')),
|
||||
buildMenuItem('selectall', i18n.getMessageFor('Select All'))
|
||||
]
|
||||
},
|
||||
{
|
||||
label: i18n.getMessageFor('View'),
|
||||
submenu: [{
|
||||
label: i18n.getMessageFor('Reload'),
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.reload();
|
||||
}
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('resetzoom', i18n.getMessageFor('Actual Size')),
|
||||
buildMenuItem('zoomin', i18n.getMessageFor('Zoom In')),
|
||||
buildMenuItem('zoomout', i18n.getMessageFor('Zoom Out')),
|
||||
{ type: 'separator' },
|
||||
buildMenuItem('togglefullscreen', i18n.getMessageFor('Toggle Full Screen')),
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
label: i18n.getMessageFor('Window'),
|
||||
submenu: [
|
||||
buildMenuItem('minimize', i18n.getMessageFor('Minimize')),
|
||||
buildMenuItem('close', i18n.getMessageFor('Close')),
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
label: i18n.getMessageFor('Help'),
|
||||
submenu:
|
||||
[
|
||||
{
|
||||
label: i18n.getMessageFor('Symphony Help'),
|
||||
click() {
|
||||
electron.shell.openExternal('https://support.symphony.com');
|
||||
}
|
||||
},
|
||||
{
|
||||
label: i18n.getMessageFor('Learn More'),
|
||||
click() {
|
||||
electron.shell.openExternal('https://www.symphony.com');
|
||||
}
|
||||
},
|
||||
{
|
||||
label: i18n.getMessageFor('Troubleshooting'),
|
||||
submenu: [
|
||||
{
|
||||
label: isMac ? i18n.getMessageFor('Show Logs in Finder') : i18n.getMessageFor('Show Logs in Explorer'),
|
||||
click(item, focusedWindow) {
|
||||
|
||||
const FILE_EXTENSIONS = ['.log'];
|
||||
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
|
||||
const WINDOWS_LOGS_PATH = '\\AppData\\Roaming\\Symphony\\logs';
|
||||
|
||||
let logsPath = isMac ? MAC_LOGS_PATH : WINDOWS_LOGS_PATH;
|
||||
let source = electron.app.getPath('home') + logsPath;
|
||||
|
||||
if (!fs.existsSync(source) && focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor('Failed!'),
|
||||
message: i18n.getMessageFor('No logs are available to share')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let destPath = isMac ? '/logs_symphony_' : '\\logs_symphony_';
|
||||
let timestamp = new Date().getTime();
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor('Failed!'),
|
||||
message: i18n.getMessageFor('Unable to generate logs due to ') + err
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
label: isMac ? i18n.getMessageFor('Show crash dump in Finder') : i18n.getMessageFor('Show crash dump in Explorer'),
|
||||
click(item, focusedWindow) {
|
||||
const FILE_EXTENSIONS = isMac ? ['.dmp'] : ['.dmp', '.txt'];
|
||||
const crashesDirectory = electron.crashReporter.getCrashesDirectory();
|
||||
let source = isMac ? crashesDirectory + '/completed' : crashesDirectory;
|
||||
|
||||
// TODO: Add support to get diagnostic reports from ~/Library/Logs/DiagnosticReports
|
||||
if (!fs.existsSync(source) || fs.readdirSync(source).length === 0 && focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor('Failed!'),
|
||||
message: i18n.getMessageFor('No crashes available to share')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let destPath = isMac ? '/crashes_symphony_' : '\\crashes_symphony_';
|
||||
let timestamp = new Date().getTime();
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor('Failed!'),
|
||||
message: i18n.getMessageFor('Unable to generate crash reports due to ') + err
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
if (isMac && template[0].label !== app.getName()) {
|
||||
template.unshift({
|
||||
label: app.getName(),
|
||||
submenu: [{
|
||||
role: 'about'
|
||||
role: 'about',
|
||||
label: i18n.getMessageFor('About Symphony')
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'services',
|
||||
label: i18n.getMessageFor('Services'),
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'hide'
|
||||
role: 'hide',
|
||||
label: i18n.getMessageFor('Hide Symphony')
|
||||
},
|
||||
{
|
||||
role: 'hideothers'
|
||||
role: 'hideothers',
|
||||
label: i18n.getMessageFor('Hide Others')
|
||||
},
|
||||
{
|
||||
role: 'unhide'
|
||||
role: 'unhide',
|
||||
label: i18n.getMessageFor('Show All')
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'quit'
|
||||
role: 'quit',
|
||||
label: i18n.getMessageFor('Quit Symphony')
|
||||
}
|
||||
]
|
||||
});
|
||||
// Edit menu.
|
||||
// Edit menu.
|
||||
template[1].submenu.push({
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Speech',
|
||||
label: i18n.getMessageFor('Speech'),
|
||||
submenu: [{
|
||||
role: 'startspeaking'
|
||||
role: 'startspeaking',
|
||||
label: i18n.getMessageFor('Start Speaking')
|
||||
},
|
||||
{
|
||||
role: 'stopspeaking'
|
||||
role: 'stopspeaking',
|
||||
label: i18n.getMessageFor('Stop Speaking')
|
||||
}
|
||||
]
|
||||
});
|
||||
// Window menu.
|
||||
// Window menu.
|
||||
template[3].submenu = [{
|
||||
label: 'Close',
|
||||
accelerator: 'CmdOrCtrl+W',
|
||||
role: 'close'
|
||||
role: 'close',
|
||||
label: i18n.getMessageFor('Close')
|
||||
},
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'CmdOrCtrl+M',
|
||||
role: 'minimize'
|
||||
role: 'minimize',
|
||||
label: i18n.getMessageFor('Minimize')
|
||||
},
|
||||
{
|
||||
label: 'Zoom',
|
||||
role: 'zoom'
|
||||
role: 'zoom',
|
||||
label: i18n.getMessageFor('Zoom')
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
role: 'front'
|
||||
role: 'front',
|
||||
label: i18n.getMessageFor('Bring All to Front')
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -266,39 +299,47 @@ function getTemplate(app) {
|
||||
type: 'separator'
|
||||
});
|
||||
|
||||
// Window menu -> launchOnStartup.
|
||||
// Window menu -> launchOnStartup.
|
||||
template[index].submenu.push({
|
||||
label: 'Auto Launch On Startup',
|
||||
label: i18n.getMessageFor('Auto Launch On Startup'),
|
||||
type: 'checkbox',
|
||||
checked: launchOnStartup,
|
||||
click: function(item, focusedWindow) {
|
||||
click: function (item, focusedWindow) {
|
||||
if (item.checked) {
|
||||
symphonyAutoLauncher.enable()
|
||||
.catch(function(err) {
|
||||
let title = 'Error setting AutoLaunch configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title, message: title + ': ' + err});
|
||||
}
|
||||
});
|
||||
.catch(function (err) {
|
||||
let title = 'Error setting AutoLaunch configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor(title),
|
||||
message: i18n.getMessageFor(title) + ': ' + err
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
symphonyAutoLauncher.disable()
|
||||
.catch(function(err) {
|
||||
let title = 'Error setting AutoLaunch configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {type: 'error', title, message: title + ': ' + err});
|
||||
}
|
||||
});
|
||||
.catch(function (err) {
|
||||
let title = 'Error setting AutoLaunch configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(focusedWindow, {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor(title),
|
||||
message: i18n.getMessageFor(title) + ': ' + err
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
launchOnStartup = item.checked;
|
||||
updateConfigField('launchOnStartup', launchOnStartup);
|
||||
}
|
||||
});
|
||||
|
||||
// Window menu -> alwaysOnTop.
|
||||
// Window menu -> alwaysOnTop.
|
||||
template[index].submenu.push({
|
||||
label: 'Always on top',
|
||||
label: i18n.getMessageFor('Always on Top'),
|
||||
type: 'checkbox',
|
||||
checked: isAlwaysOnTop,
|
||||
click: (item) => {
|
||||
@@ -311,40 +352,40 @@ function getTemplate(app) {
|
||||
}
|
||||
});
|
||||
|
||||
// Window menu -> minimizeOnClose.
|
||||
// ToDo: Add behavior on Close.
|
||||
// Window menu -> minimizeOnClose.
|
||||
// ToDo: Add behavior on Close.
|
||||
template[index].submenu.push({
|
||||
label: 'Minimize on Close',
|
||||
label: i18n.getMessageFor('Minimize on Close'),
|
||||
type: 'checkbox',
|
||||
checked: minimizeOnClose,
|
||||
click: function(item) {
|
||||
click: function (item) {
|
||||
minimizeOnClose = item.checked;
|
||||
updateConfigField('minimizeOnClose', minimizeOnClose);
|
||||
}
|
||||
});
|
||||
|
||||
// Window menu -> bringToFront
|
||||
// Window menu -> bringToFront
|
||||
template[index].submenu.push({
|
||||
label: isWindowsOS ? 'Flash Notification in Taskbar' : 'Bring to Front on Notifications',
|
||||
label: isWindowsOS ? i18n.getMessageFor('Flash Notification in Taskbar') : i18n.getMessageFor('Bring to Front on Notifications'),
|
||||
type: 'checkbox',
|
||||
checked: bringToFront,
|
||||
click: function(item) {
|
||||
click: function (item) {
|
||||
bringToFront = item.checked;
|
||||
updateConfigField('bringToFront', bringToFront);
|
||||
}
|
||||
});
|
||||
|
||||
// Window/View menu -> separator
|
||||
// Window/View menu -> separator
|
||||
template[index].submenu.push({
|
||||
type: 'separator',
|
||||
});
|
||||
|
||||
// Window - View menu -> memoryRefresh
|
||||
// Window - View menu -> memoryRefresh
|
||||
template[index].submenu.push({
|
||||
label: 'Refresh app when idle',
|
||||
label: i18n.getMessageFor('Refresh app when idle'),
|
||||
type: 'checkbox',
|
||||
checked: memoryRefresh,
|
||||
click: function(item) {
|
||||
click: function (item) {
|
||||
memoryRefresh = item.checked;
|
||||
updateConfigField('memoryRefresh', memoryRefresh);
|
||||
}
|
||||
@@ -353,12 +394,12 @@ function getTemplate(app) {
|
||||
if (!isMac) {
|
||||
|
||||
if (isWindows10()) {
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable no-param-reassign */
|
||||
template[index].submenu.push({
|
||||
label: 'Title Bar Style',
|
||||
label: i18n.getMessageFor('Title Bar Style'),
|
||||
submenu: [
|
||||
{
|
||||
label: 'Native With Custom',
|
||||
label: i18n.getMessageFor('Native With Custom'),
|
||||
type: 'checkbox',
|
||||
checked: titleBarStyle === titleBarStyles.NATIVE_WITH_CUSTOM,
|
||||
click: function (item) {
|
||||
@@ -368,7 +409,7 @@ function getTemplate(app) {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Custom',
|
||||
label: i18n.getMessageFor('Custom'),
|
||||
type: 'checkbox',
|
||||
checked: titleBarStyle === titleBarStyles.CUSTOM,
|
||||
click: function (item) {
|
||||
@@ -381,19 +422,19 @@ function getTemplate(app) {
|
||||
}, {
|
||||
type: 'separator'
|
||||
});
|
||||
/* eslint-enable no-param-reassign */
|
||||
/* eslint-enable no-param-reassign */
|
||||
}
|
||||
|
||||
template[index].submenu.push({
|
||||
label: 'Quit Symphony',
|
||||
click: function() {
|
||||
label: i18n.getMessageFor('Quit Symphony'),
|
||||
click: function () {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// This adds About Symphony under help menu for windows
|
||||
// This adds About Symphony under help menu for windows
|
||||
template[3].submenu.push({
|
||||
label: 'About Symphony',
|
||||
label: i18n.getMessageFor('About Symphony'),
|
||||
click(focusedWindow) {
|
||||
let windowName = focusedWindow ? focusedWindow.name : '';
|
||||
aboutApp.openAboutWindow(windowName);
|
||||
@@ -410,77 +451,82 @@ function getTemplate(app) {
|
||||
*/
|
||||
function setCheckboxValues() {
|
||||
return new Promise((resolve) => {
|
||||
/**
|
||||
* Method that reads multiple config fields
|
||||
*/
|
||||
/**
|
||||
* Method that reads multiple config fields
|
||||
*/
|
||||
getMultipleConfigField(configFields)
|
||||
.then(function (configData) {
|
||||
for (let key in configData) {
|
||||
if (configData.hasOwnProperty(key)) { // eslint-disable-line no-prototype-builtins
|
||||
switch (key) {
|
||||
case 'minimizeOnClose':
|
||||
minimizeOnClose = configData[key];
|
||||
break;
|
||||
case 'launchOnStartup':
|
||||
launchOnStartup = configData[key];
|
||||
break;
|
||||
case 'alwaysOnTop':
|
||||
isAlwaysOnTop = configData[key];
|
||||
eventEmitter.emit('isAlwaysOnTop', {
|
||||
isAlwaysOnTop: configData[key],
|
||||
shouldActivateMainWindow: true
|
||||
});
|
||||
break;
|
||||
case 'notificationSettings':
|
||||
eventEmitter.emit('notificationSettings', configData[key]);
|
||||
break;
|
||||
case 'bringToFront':
|
||||
bringToFront = configData[key];
|
||||
break;
|
||||
case 'isCustomTitleBar':
|
||||
titleBarStyle = configData[key] ? titleBarStyles.CUSTOM : titleBarStyles.NATIVE_WITH_CUSTOM;
|
||||
break;
|
||||
case 'memoryRefresh':
|
||||
memoryRefresh = configData[key];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
let title = 'Error loading configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: error reading configuration fields, error: ' + err);
|
||||
if (electron.BrowserWindow.getFocusedWindow() && !electron.BrowserWindow.getFocusedWindow().isDestroyed()) {
|
||||
electron.dialog.showMessageBox(electron.BrowserWindow.getFocusedWindow(), {type: 'error', title, message: title + ': ' + err});
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
.then(function (configData) {
|
||||
for (let key in configData) {
|
||||
if (configData.hasOwnProperty(key)) { // eslint-disable-line no-prototype-builtins
|
||||
switch (key) {
|
||||
case 'minimizeOnClose':
|
||||
minimizeOnClose = configData[key];
|
||||
break;
|
||||
case 'launchOnStartup':
|
||||
launchOnStartup = configData[key];
|
||||
break;
|
||||
case 'alwaysOnTop':
|
||||
isAlwaysOnTop = configData[key];
|
||||
eventEmitter.emit('isAlwaysOnTop', {
|
||||
isAlwaysOnTop: configData[key],
|
||||
shouldActivateMainWindow: true
|
||||
});
|
||||
break;
|
||||
case 'notificationSettings':
|
||||
eventEmitter.emit('notificationSettings', configData[key]);
|
||||
break;
|
||||
case 'bringToFront':
|
||||
bringToFront = configData[key];
|
||||
break;
|
||||
case 'isCustomTitleBar':
|
||||
titleBarStyle = configData[key] ? titleBarStyles.CUSTOM : titleBarStyles.NATIVE_WITH_CUSTOM;
|
||||
break;
|
||||
case 'memoryRefresh':
|
||||
memoryRefresh = configData[key];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
let title = 'Error loading configuration';
|
||||
log.send(logLevels.ERROR, 'MenuTemplate: error reading configuration fields, error: ' + err);
|
||||
if (electron.BrowserWindow.getFocusedWindow() && !electron.BrowserWindow.getFocusedWindow().isDestroyed()) {
|
||||
electron.dialog.showMessageBox(electron.BrowserWindow.getFocusedWindow(), {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor(title),
|
||||
message: i18n.getMessageFor(title) + ': ' + err
|
||||
});
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets respective accelerators w.r.t roles for the menu template
|
||||
*
|
||||
* @param role {String} The action of the menu item
|
||||
*
|
||||
* @param role {String} The action of the menu item
|
||||
* @param label {String} Menu item name
|
||||
* @return {Object}
|
||||
* @return {Object}.role The action of the menu item
|
||||
* @return {Object}.accelerator keyboard shortcuts and modifiers
|
||||
* @return {Object}.role The action of the menu item
|
||||
* @return {Object}.accelerator keyboard shortcuts and modifiers
|
||||
*/
|
||||
function buildMenuItem(role) {
|
||||
function buildMenuItem(role, label) {
|
||||
|
||||
if (isMac) {
|
||||
return { role: role }
|
||||
return label ? { role: role, label: label } : { role: role }
|
||||
}
|
||||
|
||||
if (isWindowsOS) {
|
||||
return { role: role, accelerator: windowsAccelerator[role] || '' }
|
||||
return label ? { role: role, label: label, accelerator: windowsAccelerator[role] || '' }
|
||||
: { role: role, accelerator: windowsAccelerator[role] || '' }
|
||||
}
|
||||
|
||||
return { role: role }
|
||||
return label ? { role: role, label: label } : { role: role }
|
||||
}
|
||||
|
||||
function getMinimizeOnClose() {
|
||||
|
||||
@@ -85,4 +85,16 @@ ipc.on('screens', (event, screens) => {
|
||||
screenSelector.appendChild(option);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ipc.on('i18n-notification-settings', (event, content) => {
|
||||
if (content && typeof content === 'object') {
|
||||
const i18nNodes = document.querySelectorAll('[data-i18n-text]');
|
||||
|
||||
for (let node of i18nNodes) {
|
||||
if (node.attributes['data-i18n-text'] && node.attributes['data-i18n-text'].value) {
|
||||
node.innerText = content[node.attributes['data-i18n-text'].value] || node.attributes['data-i18n-text'].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2,45 +2,45 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Symphony - Configure Notification Position</title>
|
||||
<title data-i18n-text="Symphony - Configure Notification Position"></title>
|
||||
<link rel="stylesheet" type="text/css" href="./configure-notification-position.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<header class="header">
|
||||
<span class="header__title">Notification Settings</span>
|
||||
<span class="header__title" data-i18n-text="Notification Settings"></span>
|
||||
</header>
|
||||
<div class="form">
|
||||
<form>
|
||||
<label class="label">Monitor</label>
|
||||
<label class="label" data-i18n-text="Monitor"></label>
|
||||
<div id="screens" class="main">
|
||||
<label>Notification shown on Monitor: </label>
|
||||
<label data-i18n-text="Notification shown on Monitor: "></label>
|
||||
<select class="selector" id="screen-selector" title="position">
|
||||
</select>
|
||||
</div>
|
||||
<label class="label">Position</label>
|
||||
<label class="label" data-i18n-text="Position"></label>
|
||||
<div class="main">
|
||||
<div class="first-set">
|
||||
<div class="radio">
|
||||
<label class="radio__label"><input id="upper-left" type="radio" name="position" value="upper-left">
|
||||
Top Left
|
||||
<span data-i18n-text="Top Left"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label class="radio__label">
|
||||
<input id="lower-left" type="radio" name="position" value="lower-left">
|
||||
Bottom Left
|
||||
<span data-i18n-text="Bottom Left"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="second-set">
|
||||
<div class="radio">
|
||||
<label class="radio__label">Top Right
|
||||
<label class="radio__label"><span data-i18n-text="Top Right"></span>
|
||||
<input id="upper-right" type="radio" name="position" value="upper-right">
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label class="radio__label">Bottom Right
|
||||
<label class="radio__label"><span data-i18n-text="Bottom Right"></span>
|
||||
<input id="lower-right" type="radio" name="position" value="lower-right">
|
||||
</label>
|
||||
</div>
|
||||
@@ -52,8 +52,8 @@
|
||||
|
||||
<footer class="footer">
|
||||
<div class="buttonLayout">
|
||||
<button id="cancel" class="buttonDismiss">CANCEL</button>
|
||||
<button id="ok-button" class="button">OK</button>
|
||||
<button id="cancel" class="buttonDismiss" data-i18n-text="CANCEL"></button>
|
||||
<button id="ok-button" class="button" data-i18n-text="OK"></button>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
@@ -10,8 +10,8 @@ const log = require('../../log.js');
|
||||
const logLevels = require('../../enums/logLevels.js');
|
||||
const notify = require('./../electron-notify');
|
||||
const eventEmitter = require('./../../eventEmitter');
|
||||
|
||||
const { updateConfigField } = require('../../config');
|
||||
const i18n = require('../../translation/i18n');
|
||||
|
||||
let configurationWindow;
|
||||
let screens;
|
||||
@@ -113,6 +113,8 @@ function openConfigurationWindow(windowName) {
|
||||
});
|
||||
|
||||
configurationWindow.webContents.on('did-finish-load', () => {
|
||||
const notificationSettingsContent = i18n.getMessageFor('NotificationSettings');
|
||||
configurationWindow.webContents.send('i18n-notification-settings', notificationSettingsContent);
|
||||
if (screens && screens.length >= 0) {
|
||||
configurationWindow.webContents.send('screens', screens);
|
||||
}
|
||||
|
||||
@@ -303,6 +303,18 @@ function createAPI() {
|
||||
*/
|
||||
setIsInMeeting: function (isInMeeting) {
|
||||
throttledSetIsInMeetingStatus(isInMeeting);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the language which updates the application locale
|
||||
* @param {string} locale - language identifier and a region identifier
|
||||
* Ex: en-US, ja-JP
|
||||
*/
|
||||
setLocale: function (locale) {
|
||||
local.ipcRenderer.send(apiName, {
|
||||
cmd: apiCmds.setLocale,
|
||||
locale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
22
js/translation/i18n.js
Normal file
22
js/translation/i18n.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const path = require("path");
|
||||
const fs = require('fs');
|
||||
let language;
|
||||
let loadedTranslations = {};
|
||||
|
||||
const getMessageFor = function(phrase) {
|
||||
let translation = loadedTranslations[phrase];
|
||||
if(translation === undefined) {
|
||||
translation = phrase;
|
||||
}
|
||||
return translation;
|
||||
};
|
||||
|
||||
const setLanguage = function(lng) {
|
||||
language = lng ? lng : 'en-US';
|
||||
loadedTranslations = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'locale', language + '.json'), 'utf8'));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
setLanguage: setLanguage,
|
||||
getMessageFor: getMessageFor
|
||||
};
|
||||
@@ -25,6 +25,7 @@ const { isMac, isNodeEnv, isWindows10, isWindowsOS } = require('./utils/misc');
|
||||
const { deleteIndexFolder } = require('./search/search.js');
|
||||
const { isWhitelisted, parseDomain } = require('./utils/whitelistHandler');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('./crashReporter.js');
|
||||
const i18n = require('./translation/i18n');
|
||||
|
||||
// show dialog when certificate errors occur
|
||||
require('./dialogs/showCertError.js');
|
||||
@@ -253,8 +254,8 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
mainWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash. Please reload or close this window.',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash. Please reload or close this window.'),
|
||||
buttons: ['Reload', 'Close']
|
||||
};
|
||||
|
||||
@@ -274,10 +275,17 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
addWindowKey(key, mainWindow);
|
||||
mainWindow.loadURL(url);
|
||||
|
||||
menu = electron.Menu.buildFromTemplate(getTemplate(app));
|
||||
if (!isWindows10()) {
|
||||
electron.Menu.setApplicationMenu(menu);
|
||||
}
|
||||
getConfigField('locale')
|
||||
.then((language) => {
|
||||
const lang = language || app.getLocale();
|
||||
log.send(`setting app language to ${lang}`);
|
||||
rebuildMenu(lang);
|
||||
})
|
||||
.catch((err) => {
|
||||
const lang = app.getLocale();
|
||||
log.send(`could not find language settings ${err}, defaulting to system language ${app.getLocale()}`);
|
||||
rebuildMenu(lang);
|
||||
});
|
||||
|
||||
mainWindow.on('close', function (e) {
|
||||
if (willQuitApp) {
|
||||
@@ -422,8 +430,8 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
let handleChildWindowCrashEvent = (e) => {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash. Please reload or close this window.',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash. Please reload or close this window.'),
|
||||
buttons: ['Reload', 'Close']
|
||||
};
|
||||
|
||||
@@ -494,8 +502,8 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
electron.dialog.showMessageBox(mainWindow, {
|
||||
type: 'warning',
|
||||
buttons: ['Ok'],
|
||||
title: 'Not Allowed',
|
||||
message: `Sorry, you are not allowed to access this website (${navigatedURL}), please contact your administrator for more details`,
|
||||
title: i18n.getMessageFor('Not Allowed'),
|
||||
message: i18n.getMessageFor('Sorry, you are not allowed to access this website') + ' (' + navigatedURL + '), ' + i18n.getMessageFor('please contact your administrator for more details'),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -538,10 +546,10 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
log.send(logLevels.INFO, 'permission is -> ' + userPermission);
|
||||
|
||||
if (!userPermission) {
|
||||
let fullMessage = `Your administrator has disabled ${message}. Please contact your admin for help.`;
|
||||
let fullMessage = i18n.getMessageFor('Your administrator has disabled') + message + '. ' + i18n.getMessageFor('Please contact your admin for help');
|
||||
const browserWindow = BrowserWindow.getFocusedWindow();
|
||||
if (browserWindow && !browserWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(browserWindow, {type: 'error', title: 'Permission Denied!', message: fullMessage});
|
||||
electron.dialog.showMessageBox(browserWindow, {type: 'error', title: i18n.getMessageFor('Permission Denied') + '!', message: fullMessage});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,6 +843,25 @@ eventEmitter.on('notificationSettings', (notificationSettings) => {
|
||||
display = notificationSettings.display;
|
||||
});
|
||||
|
||||
eventEmitter.on('language-changed', (opts) => {
|
||||
const lang = opts && opts.language || app.getLocale();
|
||||
log.send(logLevels.INFO, `language changed to ${lang}. Updating menu and user config`);
|
||||
rebuildMenu(lang);
|
||||
updateConfigField('locale', lang);
|
||||
});
|
||||
|
||||
function rebuildMenu(language) {
|
||||
setLanguage(language);
|
||||
menu = electron.Menu.buildFromTemplate(getTemplate(app));
|
||||
if (!isWindows10()) {
|
||||
electron.Menu.setApplicationMenu(menu);
|
||||
}
|
||||
}
|
||||
|
||||
function setLanguage(lang) {
|
||||
i18n.setLanguage(lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that gets invoked when an external display
|
||||
* is removed using electron 'display-removed' event.
|
||||
|
||||
97
locale/en-US.json
Normal file
97
locale/en-US.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"About Symphony": "About Symphony",
|
||||
"Actual Size": "Actual Size",
|
||||
"Always on Top": "Always on Top",
|
||||
"Auto Launch On Startup": "Auto Launch On Startup",
|
||||
"BasicAuth": {
|
||||
"Authentication Request": "Authentication Request",
|
||||
"Cancel": "Cancel",
|
||||
"hostname": "hostname",
|
||||
"Invalid user name/password": "Invalid user name/password",
|
||||
"Log In": "Log In",
|
||||
"Password:": "Password:",
|
||||
"Please provide your login credentials for:": "Please provide your login credentials for:",
|
||||
"User name:": "User name:"
|
||||
},
|
||||
"Bring All to Front": "Bring All to Front",
|
||||
"Bring to Front on Notifications": "Bring to Front on Notifications",
|
||||
"Close": "Close",
|
||||
"Copy": "Copy",
|
||||
"Cut": "Cut",
|
||||
"Delete": "Delete",
|
||||
"Edit": "Edit",
|
||||
"Help": "Help",
|
||||
"Hide Others": "Hide Others",
|
||||
"Hide Symphony": "Hide Symphony",
|
||||
"Learn More": "Learn More",
|
||||
"Minimize": "Minimize",
|
||||
"Minimize on Close": "Minimize on Close",
|
||||
"NotificationSettings": {
|
||||
"Bottom Left": "Bottom Left",
|
||||
"Bottom Right": "Bottom Right",
|
||||
"CANCEL": "CANCEL",
|
||||
"Monitor": "Monitor",
|
||||
"Notification Settings": "Notification Settings",
|
||||
"Notification shown on Monitor: ": "Notification shown on Monitor: ",
|
||||
"OK": "OK",
|
||||
"Position": "Position",
|
||||
"Symphony - Configure Notification Position": "Symphony - Configure Notification Position",
|
||||
"Top Left": "Top Left",
|
||||
"Top Right": "Top Right"
|
||||
},
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Quit Symphony": "Quit Symphony",
|
||||
"Redo": "Redo",
|
||||
"Refresh app when idle": "Refresh app when idle",
|
||||
"Reload": "Reload",
|
||||
"ScreenPicker": {
|
||||
"Applications": "Applications",
|
||||
"Cancel": "Cancel",
|
||||
"Choose what you'd like to share": "Choose what you'd like to share",
|
||||
"No screens or applications are currently available.": "No screens or applications are currently available.",
|
||||
"Screen Picker": "Screen Picker",
|
||||
"Screens": "Screens",
|
||||
"Select Application": "Select Application",
|
||||
"Select Screen": "Select Screen",
|
||||
"Share": "Share"
|
||||
},
|
||||
"Select All": "Select All",
|
||||
"Services": "Services",
|
||||
"Show All": "Show All",
|
||||
"Show crash dump in Finder": "Show crash dump in Finder",
|
||||
"Show Logs in Finder": "Show Logs in Finder",
|
||||
"Speech": "Speech",
|
||||
"Start Speaking": "Start Speaking",
|
||||
"Stop Speaking": "Stop Speaking",
|
||||
"Symphony Help": "Symphony Help",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Troubleshooting": "Troubleshooting",
|
||||
"Undo": "Undo",
|
||||
"View": "View",
|
||||
"Window": "Window",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Renderer Process Crashed": "Renderer Process Crashed",
|
||||
"Oops! Looks like we have had a crash.": "Oops! Looks like we have had a crash.",
|
||||
"Failed!": "Failed!",
|
||||
"No logs are available to share": "No logs are available to share",
|
||||
"Unable to generate logs due to ": "Unable to generate logs due to ",
|
||||
"Show crash dump in Explorer": "Show crash dump in Explorer",
|
||||
"No crashes available to share": "No crashes available to share",
|
||||
"Unable to generate crash reports due to ": "Unable to generate crash reports due to ",
|
||||
"Error setting AutoLaunch configuration": "Error setting AutoLaunch configuration",
|
||||
"Error loading configuration": "Error loading configuration",
|
||||
"Certificate Error": "Certificate Error",
|
||||
"Error loading URL": "Error loading URL",
|
||||
"Error loading window": "Error loading window",
|
||||
"Loading Error": "Loading Error",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! Looks like we have had a crash. Please reload or close this window.",
|
||||
"Not Allowed": "Not Allowed",
|
||||
"Sorry, you are not allowed to access this website": "Sorry, you are not allowed to access this website",
|
||||
"please contact your administrator for more details": "please contact your administrator for more details",
|
||||
"Your administrator has disabled": "Your administrator has disabled",
|
||||
"Please contact your admin for help": "Please contact your admin for help",
|
||||
"Permission Denied": "Permission Denied"
|
||||
}
|
||||
97
locale/en.json
Normal file
97
locale/en.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"About Symphony": "About Symphony",
|
||||
"Actual Size": "Actual Size",
|
||||
"Always on Top": "Always on Top",
|
||||
"Auto Launch On Startup": "Auto Launch On Startup",
|
||||
"BasicAuth": {
|
||||
"Authentication Request": "Authentication Request",
|
||||
"Cancel": "Cancel",
|
||||
"hostname": "hostname",
|
||||
"Invalid user name/password": "Invalid user name/password",
|
||||
"Log In": "Log In",
|
||||
"Password:": "Password:",
|
||||
"Please provide your login credentials for:": "Please provide your login credentials for:",
|
||||
"User name:": "User name:"
|
||||
},
|
||||
"Bring All to Front": "Bring All to Front",
|
||||
"Bring to Front on Notifications": "Bring to Front on Notifications",
|
||||
"Close": "Close",
|
||||
"Copy": "Copy",
|
||||
"Cut": "Cut",
|
||||
"Delete": "Delete",
|
||||
"Edit": "Edit",
|
||||
"Help": "Help",
|
||||
"Hide Others": "Hide Others",
|
||||
"Hide Symphony": "Hide Symphony",
|
||||
"Learn More": "Learn More",
|
||||
"Minimize": "Minimize",
|
||||
"Minimize on Close": "Minimize on Close",
|
||||
"NotificationSettings": {
|
||||
"Bottom Left": "Bottom Left",
|
||||
"Bottom Right": "Bottom Right",
|
||||
"CANCEL": "CANCEL",
|
||||
"Monitor": "Monitor",
|
||||
"Notification Settings": "Notification Settings",
|
||||
"Notification shown on Monitor: ": "Notification shown on Monitor: ",
|
||||
"OK": "OK",
|
||||
"Position": "Position",
|
||||
"Symphony - Configure Notification Position": "Symphony - Configure Notification Position",
|
||||
"Top Left": "Top Left",
|
||||
"Top Right": "Top Right"
|
||||
},
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Quit Symphony": "Quit Symphony",
|
||||
"Redo": "Redo",
|
||||
"Refresh app when idle": "Refresh app when idle",
|
||||
"Reload": "Reload",
|
||||
"ScreenPicker": {
|
||||
"Applications": "Applications",
|
||||
"Cancel": "Cancel",
|
||||
"Choose what you'd like to share": "Choose what you'd like to share",
|
||||
"No screens or applications are currently available.": "No screens or applications are currently available.",
|
||||
"Screen Picker": "Screen Picker",
|
||||
"Screens": "Screens",
|
||||
"Select Application": "Select Application",
|
||||
"Select Screen": "Select Screen",
|
||||
"Share": "Share"
|
||||
},
|
||||
"Select All": "Select All",
|
||||
"Services": "Services",
|
||||
"Show All": "Show All",
|
||||
"Show crash dump in Finder": "Show crash dump in Finder",
|
||||
"Show Logs in Finder": "Show Logs in Finder",
|
||||
"Speech": "Speech",
|
||||
"Start Speaking": "Start Speaking",
|
||||
"Stop Speaking": "Stop Speaking",
|
||||
"Symphony Help": "Symphony Help",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Troubleshooting": "Troubleshooting",
|
||||
"Undo": "Undo",
|
||||
"View": "View",
|
||||
"Window": "Window",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Renderer Process Crashed": "Renderer Process Crashed",
|
||||
"Oops! Looks like we have had a crash.": "Oops! Looks like we have had a crash.",
|
||||
"Failed!": "Failed!",
|
||||
"No logs are available to share": "No logs are available to share",
|
||||
"Unable to generate logs due to ": "Unable to generate logs due to ",
|
||||
"Show crash dump in Explorer": "Show crash dump in Explorer",
|
||||
"No crashes available to share": "No crashes available to share",
|
||||
"Unable to generate crash reports due to ": "Unable to generate crash reports due to ",
|
||||
"Error setting AutoLaunch configuration": "Error setting AutoLaunch configuration",
|
||||
"Error loading configuration": "Error loading configuration",
|
||||
"Certificate Error": "Certificate Error",
|
||||
"Error loading URL": "Error loading URL",
|
||||
"Error loading window": "Error loading window",
|
||||
"Loading Error": "Loading Error",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! Looks like we have had a crash. Please reload or close this window.",
|
||||
"Not Allowed": "Not Allowed",
|
||||
"Sorry, you are not allowed to access this website": "Sorry, you are not allowed to access this website",
|
||||
"please contact your administrator for more details": "please contact your administrator for more details",
|
||||
"Your administrator has disabled": "Your administrator has disabled",
|
||||
"Please contact your admin for help": "Please contact your admin for help",
|
||||
"Permission Denied": "Permission Denied"
|
||||
}
|
||||
104
locale/ja-JP.json
Normal file
104
locale/ja-JP.json
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"About Symphony": "Symphonyについて",
|
||||
"Actual Size": "実際のサイズ",
|
||||
"Always on Top": "常にトップに表示",
|
||||
"Auto Launch On Startup": "スタートアップ時の自動起動",
|
||||
"BasicAuth": {
|
||||
"Authentication Request": "認証の要求",
|
||||
"Cancel": "キャンセル",
|
||||
"hostname": "ホスト名",
|
||||
"Invalid user name/password": "ユーザー名またはパスワードが無効です",
|
||||
"Log In": "ログイン",
|
||||
"Password:": "パスワード:",
|
||||
"Please provide your login credentials for:": "あなたのログイン資格情報を入力してください:",
|
||||
"User name:": "ユーザー名:"
|
||||
},
|
||||
"Bring All to Front": "すべてを前面に表示",
|
||||
"Bring to Front on Notifications": "通知の前面に表示",
|
||||
"Close": "閉じる",
|
||||
"Copy": "コピー",
|
||||
"Cut": "切り取り",
|
||||
"Delete": "削除",
|
||||
"Edit": "編集",
|
||||
"Help": "ヘルプ",
|
||||
"Hide Others": "他を隠す",
|
||||
"Hide Symphony": "Symphonyを隠す",
|
||||
"Learn More": "詳細を表示",
|
||||
"Minimize": "最小化",
|
||||
"Minimize on Close": "閉じる時に最小化",
|
||||
"NotificationSettings": {
|
||||
"Bottom Left": "左下",
|
||||
"Bottom Right": "右下",
|
||||
"CANCEL": "キャンセル",
|
||||
"Monitor": "モニター",
|
||||
"Notification Settings": "通知設定",
|
||||
"Notification shown on Monitor: ": "モニターに表示される通知:",
|
||||
"OK": "OK",
|
||||
"Position": "位置",
|
||||
"Symphony - Configure Notification Position": "Symphony - 通知位置の設定",
|
||||
"Top Left": "左上",
|
||||
"Top Right": "右上"
|
||||
},
|
||||
"Paste": "ペースト",
|
||||
"Paste and Match Style": "ペーストしてスタイルを合わせる",
|
||||
"Quit Symphony": "Symphonyの終了",
|
||||
"Redo": "やり直し",
|
||||
"Refresh app when idle": "アイドル時にアプリを更新する",
|
||||
"Reload": "再ロード",
|
||||
"ScreenPicker": {
|
||||
"Applications": "アプリケーション",
|
||||
"Cancel": "キャンセル",
|
||||
"Choose what you'd like to share": "共有するものを選択する",
|
||||
"No screens or applications are currently available.": "現在利用可能な画面やアプリケーションはありません。",
|
||||
"Screen Picker": "画面の選択",
|
||||
"Screens": "画面",
|
||||
"Select Application": "アプリケーションの選択",
|
||||
"Select Screen": "画面の選択",
|
||||
"Share": "共有"
|
||||
},
|
||||
"ScreenSnippet": {
|
||||
"Pen": "ペン",
|
||||
"Done": "完了",
|
||||
"Snipping Tool": "スニッピングツール",
|
||||
"Erase": "消去する",
|
||||
"Highlight": "ハイライト"
|
||||
},
|
||||
"Select All": "すべてを選択",
|
||||
"Services": "サービス",
|
||||
"Show All": "すべてを表示",
|
||||
"Show crash dump in Finder": "ファインダーにクラッシュダンプを表示",
|
||||
"Show Logs in Finder": "ファインダーにログを表示",
|
||||
"Speech": "スピーチ",
|
||||
"Start Speaking": "スピーキングを始める",
|
||||
"Stop Speaking": "スピーキングをやめる",
|
||||
"Symphony Help": "Symphonyヘルプ",
|
||||
"Toggle Full Screen": "フルスクリーン切り替え",
|
||||
"Troubleshooting": "トラブルシューティング",
|
||||
"Undo": "元に戻す",
|
||||
"View": "ビュー",
|
||||
"Window": "ウインドウ",
|
||||
"Zoom": "ズーム",
|
||||
"Zoom In": "ズームイン",
|
||||
"Zoom Out": "ズームアウト",
|
||||
"Renderer Process Crashed": "レンダラープロセスがクラッシュしました",
|
||||
"Oops! Looks like we have had a crash.": "おっと!クラッシュしたようです。",
|
||||
"Failed!": "失敗!",
|
||||
"No logs are available to share": "共有できるログはありません",
|
||||
"Unable to generate logs due to ": "以下が原因でログを生成できません ",
|
||||
"Show crash dump in Explorer": "Explorerにクラッシュダンプを表示",
|
||||
"No crashes available to share": "共有できるクラッシュはありません",
|
||||
"Unable to generate crash reports due to ": "以下が原因でクラッシュレポートを生成できません ",
|
||||
"Error setting AutoLaunch configuration": "自動起動設定の設定エラー",
|
||||
"Error loading configuration": "設定を読み込む際のエラー",
|
||||
"Certificate Error": "証明エラー",
|
||||
"Error loading URL": "URLの読み込みエラー",
|
||||
"Error loading window": "ウィンドウを読み込む際のエラー",
|
||||
"Loading Error": "読み込みエラー",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "おっと!クラッシュしたようです。このウィンドウをリロードしてください。",
|
||||
"Not Allowed": "未許可",
|
||||
"Sorry, you are not allowed to access this website": "申し訳ありませんが、このウェブサイトへのアクセスは許可されていません",
|
||||
"please contact your administrator for more details": "詳細については、管理者にお問い合わせください",
|
||||
"Your administrator has disabled": "管理者が無効にしました",
|
||||
"Please contact your admin for help": "ヘルプについては管理者にお問い合わせください",
|
||||
"Permission Denied": "許可が拒否されました"
|
||||
}
|
||||
97
locale/ja.json
Normal file
97
locale/ja.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"About Symphony": "Symphonyについて",
|
||||
"Actual Size": "実際のサイズ",
|
||||
"Always on Top": "常にトップに表示",
|
||||
"Auto Launch On Startup": "スタートアップ時の自動起動",
|
||||
"BasicAuth": {
|
||||
"Authentication Request": "認証の要求",
|
||||
"Cancel": "キャンセル",
|
||||
"hostname": "ホスト名",
|
||||
"Invalid user name/password": "ユーザー名またはパスワードが無効です",
|
||||
"Log In": "ログイン",
|
||||
"Password:": "パスワード:",
|
||||
"Please provide your login credentials for:": "あなたのログイン資格情報を入力してください:",
|
||||
"User name:": "ユーザー名:"
|
||||
},
|
||||
"Bring All to Front": "すべてを前面に表示",
|
||||
"Bring to Front on Notifications": "通知の前面に表示",
|
||||
"Close": "閉じる",
|
||||
"Copy": "コピー",
|
||||
"Cut": "切り取り",
|
||||
"Delete": "削除",
|
||||
"Edit": "編集",
|
||||
"Help": "ヘルプ",
|
||||
"Hide Others": "他を隠す",
|
||||
"Hide Symphony": "Symphonyを隠す",
|
||||
"Learn More": "詳細を表示",
|
||||
"Minimize": "最小化",
|
||||
"Minimize on Close": "閉じる時に最小化",
|
||||
"NotificationSettings": {
|
||||
"Bottom Left": "左下",
|
||||
"Bottom Right": "右下",
|
||||
"CANCEL": "キャンセル",
|
||||
"Monitor": "モニター",
|
||||
"Notification Settings": "通知設定",
|
||||
"Notification shown on Monitor: ": "モニターに表示される通知:",
|
||||
"OK": "OK",
|
||||
"Position": "位置",
|
||||
"Symphony - Configure Notification Position": "Symphony - 通知位置の設定",
|
||||
"Top Left": "左上",
|
||||
"Top Right": "右上"
|
||||
},
|
||||
"Paste": "ペースト",
|
||||
"Paste and Match Style": "ペーストしてスタイルを合わせる",
|
||||
"Quit Symphony": "Symphonyの終了",
|
||||
"Redo": "やり直し",
|
||||
"Refresh app when idle": "アイドル時にアプリを更新する",
|
||||
"Reload": "再ロード",
|
||||
"ScreenPicker": {
|
||||
"Applications": "アプリケーション",
|
||||
"Cancel": "キャンセル",
|
||||
"Choose what you'd like to share": "共有するものを選択する",
|
||||
"No screens or applications are currently available.": "現在利用可能な画面やアプリケーションはありません。",
|
||||
"Screen Picker": "画面の選択",
|
||||
"Screens": "画面",
|
||||
"Select Application": "アプリケーションの選択",
|
||||
"Select Screen": "画面の選択",
|
||||
"Share": "共有"
|
||||
},
|
||||
"Select All": "すべてを選択",
|
||||
"Services": "サービス",
|
||||
"Show All": "すべてを表示",
|
||||
"Show crash dump in Finder": "ファインダーにクラッシュダンプを表示",
|
||||
"Show Logs in Finder": "ファインダーにログを表示",
|
||||
"Speech": "スピーチ",
|
||||
"Start Speaking": "スピーキングを始める",
|
||||
"Stop Speaking": "スピーキングをやめる",
|
||||
"Symphony Help": "Symphonyヘルプ",
|
||||
"Toggle Full Screen": "フルスクリーン切り替え",
|
||||
"Troubleshooting": "トラブルシューティング",
|
||||
"Undo": "元に戻す",
|
||||
"View": "ビュー",
|
||||
"Window": "ウインドウ",
|
||||
"Zoom": "ズーム",
|
||||
"Zoom In": "ズームイン",
|
||||
"Zoom Out": "ズームアウト",
|
||||
"Renderer Process Crashed": "レンダラープロセスがクラッシュしました",
|
||||
"Oops! Looks like we have had a crash.": "おっと!クラッシュしたようです。",
|
||||
"Failed!": "失敗!",
|
||||
"No logs are available to share": "共有できるログはありません",
|
||||
"Unable to generate logs due to ": "以下が原因でログを生成できません ",
|
||||
"Show crash dump in Explorer": "Explorerにクラッシュダンプを表示",
|
||||
"No crashes available to share": "共有できるクラッシュはありません",
|
||||
"Unable to generate crash reports due to ": "以下が原因でクラッシュレポートを生成できません ",
|
||||
"Error setting AutoLaunch configuration": "自動起動設定の設定エラー",
|
||||
"Error loading configuration": "設定を読み込む際のエラー",
|
||||
"Certificate Error": "証明エラー",
|
||||
"Error loading URL": "URLの読み込みエラー",
|
||||
"Error loading window": "ウィンドウを読み込む際のエラー",
|
||||
"Loading Error": "読み込みエラー",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "おっと!クラッシュしたようです。このウィンドウをリロードしてください。",
|
||||
"Not Allowed": "未許可",
|
||||
"Sorry, you are not allowed to access this website": "申し訳ありませんが、このウェブサイトへのアクセスは許可されていません",
|
||||
"please contact your administrator for more details": "詳細については、管理者にお問い合わせください",
|
||||
"Your administrator has disabled": "管理者が無効にしました",
|
||||
"Please contact your admin for help": "ヘルプについては管理者にお問い合わせください",
|
||||
"Permission Denied": "許可が拒否されました"
|
||||
}
|
||||
Reference in New Issue
Block a user