escape menu labels

fixes #1456
pull/1457/head
Mikael Finstad 3 years ago
parent 05348e9bd0
commit 4e60037e09
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -1,6 +1,10 @@
const electron = require('electron'); const electron = require('electron');
const i18n = require('i18next'); const i18n = require('i18next');
// menu-safe i18n.t:
// https://github.com/mifi/lossless-cut/issues/1456
const t = (key) => i18n.t(key).replace(/&/g, '&&');
const { Menu } = electron; const { Menu } = electron;
const { homepage, getReleaseUrl, licensesPage } = require('./constants'); const { homepage, getReleaseUrl, licensesPage } = require('./constants');
@ -10,88 +14,88 @@ module.exports = (app, mainWindow, newVersion) => {
...(process.platform === 'darwin' ? [{ role: 'appMenu' }] : []), ...(process.platform === 'darwin' ? [{ role: 'appMenu' }] : []),
{ {
label: i18n.t('File'), label: t('File'),
submenu: [ submenu: [
{ {
label: i18n.t('Open'), label: t('Open'),
accelerator: 'CmdOrCtrl+O', accelerator: 'CmdOrCtrl+O',
async click() { async click() {
mainWindow.webContents.send('openFilesDialog'); mainWindow.webContents.send('openFilesDialog');
}, },
}, },
{ {
label: i18n.t('Close'), label: t('Close'),
accelerator: 'CmdOrCtrl+W', accelerator: 'CmdOrCtrl+W',
async click() { async click() {
mainWindow.webContents.send('closeCurrentFile'); mainWindow.webContents.send('closeCurrentFile');
}, },
}, },
{ {
label: i18n.t('Close batch'), label: t('Close batch'),
async click() { async click() {
mainWindow.webContents.send('closeBatchFiles'); mainWindow.webContents.send('closeBatchFiles');
}, },
}, },
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Import project (LLC)...'), label: t('Import project (LLC)...'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'llc'); mainWindow.webContents.send('importEdlFile', 'llc');
}, },
}, },
{ {
label: i18n.t('Export project (LLC)...'), label: t('Export project (LLC)...'),
click() { click() {
mainWindow.webContents.send('exportEdlFile', 'llc'); mainWindow.webContents.send('exportEdlFile', 'llc');
}, },
}, },
{ {
label: i18n.t('Import project'), label: t('Import project'),
submenu: [ submenu: [
{ {
label: i18n.t('Times in seconds (CSV)'), label: t('Times in seconds (CSV)'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'csv'); mainWindow.webContents.send('importEdlFile', 'csv');
}, },
}, },
{ {
label: i18n.t('Frame numbers (CSV)'), label: t('Frame numbers (CSV)'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'csv-frames'); mainWindow.webContents.send('importEdlFile', 'csv-frames');
}, },
}, },
{ {
label: i18n.t('EDL (MPlayer)'), label: t('EDL (MPlayer)'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'mplayer'); mainWindow.webContents.send('importEdlFile', 'mplayer');
}, },
}, },
{ {
label: i18n.t('Text chapters / YouTube'), label: t('Text chapters / YouTube'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'youtube'); mainWindow.webContents.send('importEdlFile', 'youtube');
}, },
}, },
{ {
label: i18n.t('DaVinci Resolve / Final Cut Pro XML'), label: t('DaVinci Resolve / Final Cut Pro XML'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'xmeml'); mainWindow.webContents.send('importEdlFile', 'xmeml');
}, },
}, },
{ {
label: i18n.t('Final Cut Pro FCPX / FCPXML'), label: t('Final Cut Pro FCPX / FCPXML'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'fcpxml'); mainWindow.webContents.send('importEdlFile', 'fcpxml');
}, },
}, },
{ {
label: i18n.t('CUE sheet file'), label: t('CUE sheet file'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'cue'); mainWindow.webContents.send('importEdlFile', 'cue');
}, },
}, },
{ {
label: i18n.t('PotPlayer Bookmarks (.pbf)'), label: t('PotPlayer Bookmarks (.pbf)'),
click() { click() {
mainWindow.webContents.send('importEdlFile', 'pbf'); mainWindow.webContents.send('importEdlFile', 'pbf');
}, },
@ -99,34 +103,34 @@ module.exports = (app, mainWindow, newVersion) => {
], ],
}, },
{ {
label: i18n.t('Export project'), label: t('Export project'),
submenu: [ submenu: [
{ {
label: i18n.t('Times in seconds (CSV)'), label: t('Times in seconds (CSV)'),
click() { click() {
mainWindow.webContents.send('exportEdlFile', 'csv'); mainWindow.webContents.send('exportEdlFile', 'csv');
}, },
}, },
{ {
label: i18n.t('Timestamps (CSV)'), label: t('Timestamps (CSV)'),
click() { click() {
mainWindow.webContents.send('exportEdlFile', 'csv-human'); mainWindow.webContents.send('exportEdlFile', 'csv-human');
}, },
}, },
{ {
label: i18n.t('Frame numbers (CSV)'), label: t('Frame numbers (CSV)'),
click() { click() {
mainWindow.webContents.send('exportEdlFile', 'csv-frames'); mainWindow.webContents.send('exportEdlFile', 'csv-frames');
}, },
}, },
{ {
label: i18n.t('Timestamps (TSV/TXT)'), label: t('Timestamps (TSV/TXT)'),
click() { click() {
mainWindow.webContents.send('exportEdlFile', 'tsv-human'); mainWindow.webContents.send('exportEdlFile', 'tsv-human');
}, },
}, },
{ {
label: i18n.t('Start times as YouTube Chapters'), label: t('Start times as YouTube Chapters'),
click() { click() {
mainWindow.webContents.send('exportEdlYouTube'); mainWindow.webContents.send('exportEdlYouTube');
}, },
@ -135,13 +139,13 @@ module.exports = (app, mainWindow, newVersion) => {
}, },
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Convert to supported format'), label: t('Convert to supported format'),
click() { click() {
mainWindow.webContents.send('html5ify'); mainWindow.webContents.send('html5ify');
}, },
}, },
{ {
label: i18n.t('Fix incorrect duration'), label: t('Fix incorrect duration'),
click() { click() {
mainWindow.webContents.send('fixInvalidDuration'); mainWindow.webContents.send('fixInvalidDuration');
}, },
@ -150,7 +154,7 @@ module.exports = (app, mainWindow, newVersion) => {
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Settings'), label: t('Settings'),
accelerator: 'CmdOrCtrl+,', accelerator: 'CmdOrCtrl+,',
click() { click() {
mainWindow.webContents.send('toggleSettings'); mainWindow.webContents.send('toggleSettings');
@ -161,7 +165,7 @@ module.exports = (app, mainWindow, newVersion) => {
...(process.platform !== 'darwin' ? [ ...(process.platform !== 'darwin' ? [
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Exit'), label: t('Exit'),
click() { click() {
app.quit(); app.quit();
}, },
@ -171,83 +175,83 @@ module.exports = (app, mainWindow, newVersion) => {
}, },
{ {
label: i18n.t('Edit'), label: t('Edit'),
submenu: [ submenu: [
// https://github.com/mifi/lossless-cut/issues/610 // https://github.com/mifi/lossless-cut/issues/610
// https://github.com/mifi/lossless-cut/issues/1183 // https://github.com/mifi/lossless-cut/issues/1183
{ role: 'undo', label: i18n.t('Undo') }, { role: 'undo', label: t('Undo') },
{ role: 'redo', label: i18n.t('Redo') }, { role: 'redo', label: t('Redo') },
{ type: 'separator' }, { type: 'separator' },
{ role: 'cut', label: i18n.t('Cut') }, { role: 'cut', label: t('Cut') },
{ role: 'copy', label: i18n.t('Copy') }, { role: 'copy', label: t('Copy') },
{ role: 'paste', label: i18n.t('Paste') }, { role: 'paste', label: t('Paste') },
{ role: 'selectall', label: i18n.t('Select All') }, { role: 'selectall', label: t('Select All') },
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Segments'), label: t('Segments'),
submenu: [ submenu: [
{ {
label: i18n.t('Clear all segments'), label: t('Clear all segments'),
click() { click() {
mainWindow.webContents.send('clearSegments'); mainWindow.webContents.send('clearSegments');
}, },
}, },
{ {
label: i18n.t('Reorder segments by start time'), label: t('Reorder segments by start time'),
click() { click() {
mainWindow.webContents.send('reorderSegsByStartTime'); mainWindow.webContents.send('reorderSegsByStartTime');
}, },
}, },
{ {
label: i18n.t('Create num segments'), label: t('Create num segments'),
click() { click() {
mainWindow.webContents.send('createNumSegments'); mainWindow.webContents.send('createNumSegments');
}, },
}, },
{ {
label: i18n.t('Create fixed duration segments'), label: t('Create fixed duration segments'),
click() { click() {
mainWindow.webContents.send('createFixedDurationSegments'); mainWindow.webContents.send('createFixedDurationSegments');
}, },
}, },
{ {
label: i18n.t('Create random segments'), label: t('Create random segments'),
click() { click() {
mainWindow.webContents.send('createRandomSegments'); mainWindow.webContents.send('createRandomSegments');
}, },
}, },
{ {
label: i18n.t('Invert all segments on timeline'), label: t('Invert all segments on timeline'),
click() { click() {
mainWindow.webContents.send('invertAllSegments'); mainWindow.webContents.send('invertAllSegments');
}, },
}, },
{ {
label: i18n.t('Fill gaps between segments'), label: t('Fill gaps between segments'),
click() { click() {
mainWindow.webContents.send('fillSegmentsGaps'); mainWindow.webContents.send('fillSegmentsGaps');
}, },
}, },
{ {
label: i18n.t('Combine overlapping segments'), label: t('Combine overlapping segments'),
click() { click() {
mainWindow.webContents.send('combineOverlappingSegments'); mainWindow.webContents.send('combineOverlappingSegments');
}, },
}, },
{ {
label: i18n.t('Shuffle segments order'), label: t('Shuffle segments order'),
click() { click() {
mainWindow.webContents.send('shuffleSegments'); mainWindow.webContents.send('shuffleSegments');
}, },
}, },
{ {
label: i18n.t('Shift all segments on timeline'), label: t('Shift all segments on timeline'),
click() { click() {
mainWindow.webContents.send('shiftAllSegmentTimes'); mainWindow.webContents.send('shiftAllSegmentTimes');
}, },
}, },
{ {
label: i18n.t('Align segment times to keyframes'), label: t('Align segment times to keyframes'),
click() { click() {
mainWindow.webContents.send('alignSegmentTimesToKeyframes'); mainWindow.webContents.send('alignSegmentTimesToKeyframes');
}, },
@ -255,16 +259,16 @@ module.exports = (app, mainWindow, newVersion) => {
], ],
}, },
{ {
label: i18n.t('Tracks'), label: t('Tracks'),
submenu: [ submenu: [
{ {
label: i18n.t('Extract all tracks'), label: t('Extract all tracks'),
click() { click() {
mainWindow.webContents.send('extractAllStreams'); mainWindow.webContents.send('extractAllStreams');
}, },
}, },
{ {
label: i18n.t('Edit tracks / metadata tags'), label: t('Edit tracks / metadata tags'),
click() { click() {
mainWindow.webContents.send('showStreamsSelector'); mainWindow.webContents.send('showStreamsSelector');
}, },
@ -275,105 +279,105 @@ module.exports = (app, mainWindow, newVersion) => {
}, },
{ {
label: i18n.t('View'), label: t('View'),
submenu: [ submenu: [
{ role: 'togglefullscreen', label: i18n.t('Toggle Full Screen') }, { role: 'togglefullscreen', label: t('Toggle Full Screen') },
], ],
}, },
// On Windows the windowMenu has a close Ctrl+W which clashes with File->Close shortcut // On Windows the windowMenu has a close Ctrl+W which clashes with File->Close shortcut
...(process.platform === 'darwin' ...(process.platform === 'darwin'
? [{ role: 'windowMenu', label: i18n.t('Window') }] ? [{ role: 'windowMenu', label: t('Window') }]
: [{ : [{
label: i18n.t('Window'), label: t('Window'),
submenu: [{ role: 'minimize', label: i18n.t('Minimize') }], submenu: [{ role: 'minimize', label: t('Minimize') }],
}] }]
), ),
{ {
label: i18n.t('Tools'), label: t('Tools'),
submenu: [ submenu: [
{ {
label: i18n.t('Merge/concatenate files'), label: t('Merge/concatenate files'),
click() { click() {
mainWindow.webContents.send('concatCurrentBatch'); mainWindow.webContents.send('concatCurrentBatch');
}, },
}, },
{ {
label: i18n.t('Set custom start offset/timecode'), label: t('Set custom start offset/timecode'),
click() { click() {
mainWindow.webContents.send('askSetStartTimeOffset'); mainWindow.webContents.send('askSetStartTimeOffset');
}, },
}, },
{ {
label: i18n.t('Detect black scenes'), label: t('Detect black scenes'),
click() { click() {
mainWindow.webContents.send('detectBlackScenes'); mainWindow.webContents.send('detectBlackScenes');
}, },
}, },
{ {
label: i18n.t('Detect silent scenes'), label: t('Detect silent scenes'),
click() { click() {
mainWindow.webContents.send('detectSilentScenes'); mainWindow.webContents.send('detectSilentScenes');
}, },
}, },
{ {
label: i18n.t('Detect scene changes'), label: t('Detect scene changes'),
click() { click() {
mainWindow.webContents.send('detectSceneChanges'); mainWindow.webContents.send('detectSceneChanges');
}, },
}, },
{ {
label: i18n.t('Create segments from keyframes'), label: t('Create segments from keyframes'),
click() { click() {
mainWindow.webContents.send('createSegmentsFromKeyframes'); mainWindow.webContents.send('createSegmentsFromKeyframes');
}, },
}, },
{ {
label: i18n.t('Last ffmpeg commands'), label: t('Last ffmpeg commands'),
click() { mainWindow.webContents.send('toggleLastCommands'); }, click() { mainWindow.webContents.send('toggleLastCommands'); },
}, },
{ type: 'separator' }, { type: 'separator' },
{ role: 'toggleDevTools', label: i18n.t('Toggle Developer Tools') }, { role: 'toggleDevTools', label: t('Toggle Developer Tools') },
], ],
}, },
{ {
role: 'help', role: 'help',
label: i18n.t('Help'), label: t('Help'),
submenu: [ submenu: [
{ {
label: i18n.t('How to use'), label: t('How to use'),
click() { electron.shell.openExternal('https://mifi.no/losslesscut/usage'); }, click() { electron.shell.openExternal('https://mifi.no/losslesscut/usage'); },
}, },
{ {
label: i18n.t('FAQ'), label: t('FAQ'),
click() { electron.shell.openExternal('https://mifi.no/losslesscut/faq'); }, click() { electron.shell.openExternal('https://mifi.no/losslesscut/faq'); },
}, },
{ {
label: i18n.t('Troubleshooting'), label: t('Troubleshooting'),
click() { electron.shell.openExternal('https://mifi.no/losslesscut/troubleshooting'); }, click() { electron.shell.openExternal('https://mifi.no/losslesscut/troubleshooting'); },
}, },
{ {
label: i18n.t('Learn More'), label: t('Learn More'),
click() { electron.shell.openExternal(homepage); }, click() { electron.shell.openExternal(homepage); },
}, },
{ {
label: i18n.t('Licenses'), label: t('Licenses'),
click() { electron.shell.openExternal(licensesPage); }, click() { electron.shell.openExternal(licensesPage); },
}, },
{ type: 'separator' }, { type: 'separator' },
{ {
label: i18n.t('Keyboard & mouse shortcuts'.replace(/&/g, '&&')), label: t('Keyboard & mouse shortcuts'),
click() { click() {
mainWindow.webContents.send('toggleKeyboardShortcuts'); mainWindow.webContents.send('toggleKeyboardShortcuts');
}, },
}, },
{ {
label: i18n.t('Report an error'), label: t('Report an error'),
click() { mainWindow.webContents.send('openSendReportDialog'); }, click() { mainWindow.webContents.send('openSendReportDialog'); },
}, },
{ {
label: i18n.t('Version'), label: t('Version'),
click() { mainWindow.webContents.send('openAbout'); }, click() { mainWindow.webContents.send('openAbout'); },
}, },
], ],
@ -382,10 +386,10 @@ module.exports = (app, mainWindow, newVersion) => {
if (newVersion) { if (newVersion) {
menu.push({ menu.push({
label: i18n.t('New version!'), label: t('New version!'),
submenu: [ submenu: [
{ {
label: i18n.t('Download {{version}}', { version: newVersion }), label: t('Download {{version}}', { version: newVersion }),
click() { electron.shell.openExternal(getReleaseUrl(newVersion)); }, click() { electron.shell.openExternal(getReleaseUrl(newVersion)); },
}, },
], ],

Loading…
Cancel
Save