Add interpolation for fallback dialog messages

This commit is contained in:
Josh Perez 2020-02-13 10:14:08 -08:00 committed by GitHub
parent 800c7ed31d
commit afddc852cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 47 deletions

View file

@ -1,6 +1,7 @@
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
const { setup } = require('../js/modules/i18n');
function normalizeLocaleName(locale) {
if (/^en-/.test(locale)) {
@ -58,7 +59,10 @@ function load({ appLocale, logger } = {}) {
messages = english;
}
const i18n = setup(appLocale, messages);
return {
i18n,
name: localeName,
messages,
};

View file

@ -421,7 +421,7 @@ async function readyForUpdates() {
// Second, start checking for app updates
try {
await updater.start(getMainWindow, locale.messages, logger);
await updater.start(getMainWindow, locale, logger);
} catch (error) {
logger.error(
'Error starting update checks:',

View file

@ -8,6 +8,13 @@ describe('i18n', () => {
it('returns message for given string', () => {
assert.equal(i18n('reportIssue'), 'Report an issue');
});
it('returns message with single substitution', () => {
const actual = i18n('cannotUpdateDetail', 'https://signal.org/download');
assert.equal(
actual,
'Signal Desktop failed to update, but there is a new version available. Please go to https://signal.org/download and install the new version manually, then either contact support or file a bug about this problem.'
);
});
it('returns message with multiple substitutions', () => {
const actual = i18n('theyChangedTheTimer', ['Someone', '5 minutes']);
assert.equal(

View file

@ -27,10 +27,13 @@ import { Dialogs } from '../types/Dialogs';
import * as packageJson from '../../package.json';
import { getSignatureFileName } from './signature';
export type MessagesType = {
[key: string]: {
message: string;
description?: string;
export type LocaleType = {
i18n: (key: string, placeholders: Array<string>) => string;
messages: {
[key: string]: {
message: string;
description?: string;
};
};
};
@ -146,19 +149,19 @@ export async function downloadUpdate(
async function showFallbackUpdateDialog(
mainWindow: BrowserWindow,
messages: MessagesType
locale: LocaleType
) {
const RESTART_BUTTON = 0;
const LATER_BUTTON = 1;
const options = {
type: 'info',
buttons: [
messages.autoUpdateRestartButtonLabel.message,
messages.autoUpdateLaterButtonLabel.message,
locale.messages.autoUpdateRestartButtonLabel.message,
locale.messages.autoUpdateLaterButtonLabel.message,
],
title: messages.autoUpdateNewVersionTitle.message,
message: messages.autoUpdateNewVersionMessage.message,
detail: messages.autoUpdateNewVersionInstructions.message,
title: locale.messages.autoUpdateNewVersionTitle.message,
message: locale.messages.autoUpdateNewVersionMessage.message,
detail: locale.messages.autoUpdateNewVersionInstructions.message,
defaultId: LATER_BUTTON,
cancelId: LATER_BUTTON,
};
@ -170,7 +173,7 @@ async function showFallbackUpdateDialog(
export function showUpdateDialog(
mainWindow: BrowserWindow,
messages: MessagesType,
locale: LocaleType,
performUpdateCallback: () => void
): void {
let ack = false;
@ -185,20 +188,20 @@ export function showUpdateDialog(
setTimeout(async () => {
if (!ack) {
await showFallbackUpdateDialog(mainWindow, messages);
await showFallbackUpdateDialog(mainWindow, locale);
}
}, ACK_RENDER_TIMEOUT);
}
async function showFallbackCannotUpdateDialog(
mainWindow: BrowserWindow,
messages: MessagesType
locale: LocaleType
) {
const options = {
type: 'error',
buttons: [messages.ok.message],
title: messages.cannotUpdate.message,
message: messages.cannotUpdateDetail.message,
buttons: [locale.messages.ok.message],
title: locale.messages.cannotUpdate.message,
message: locale.i18n('cannotUpdateDetail', ['https://signal.org/download']),
};
await dialog.showMessageBox(mainWindow, options);
@ -206,7 +209,7 @@ async function showFallbackCannotUpdateDialog(
export function showCannotUpdateDialog(
mainWindow: BrowserWindow,
messages: MessagesType
locale: LocaleType
): void {
let ack = false;
@ -218,7 +221,7 @@ export function showCannotUpdateDialog(
setTimeout(async () => {
if (!ack) {
await showFallbackCannotUpdateDialog(mainWindow, messages);
await showFallbackCannotUpdateDialog(mainWindow, locale);
}
}, ACK_RENDER_TIMEOUT);
}

View file

@ -3,13 +3,13 @@ import { BrowserWindow } from 'electron';
import { start as startMacOS } from './macos';
import { start as startWindows } from './windows';
import { LoggerType, MessagesType } from './common';
import { LocaleType, LoggerType } from './common';
let initialized = false;
export async function start(
getMainWindow: () => BrowserWindow,
messages?: MessagesType,
locale?: LocaleType,
logger?: LoggerType
) {
const { platform } = process;
@ -19,8 +19,8 @@ export async function start(
}
initialized = true;
if (!messages) {
throw new Error('updater/start: Must provide messages!');
if (!locale) {
throw new Error('updater/start: Must provide locale!');
}
if (!logger) {
throw new Error('updater/start: Must provide logger!');
@ -35,9 +35,9 @@ export async function start(
}
if (platform === 'win32') {
await startWindows(getMainWindow, messages, logger);
await startWindows(getMainWindow, locale, logger);
} else if (platform === 'darwin') {
await startMacOS(getMainWindow, messages, logger);
await startMacOS(getMainWindow, locale, logger);
} else {
throw new Error('updater/start: Unsupported platform');
}

View file

@ -15,8 +15,8 @@ import {
deleteTempDir,
downloadUpdate,
getPrintableError,
LocaleType,
LoggerType,
MessagesType,
showCannotUpdateDialog,
showUpdateDialog,
} from './common';
@ -31,7 +31,7 @@ const INTERVAL = MINUTE * 30;
export async function start(
getMainWindow: () => BrowserWindow,
messages: MessagesType,
locale: LocaleType,
logger: LoggerType
) {
logger.info('macos/start: starting checks...');
@ -41,13 +41,13 @@ export async function start(
setInterval(async () => {
try {
await checkDownloadAndInstall(getMainWindow, messages, logger);
await checkDownloadAndInstall(getMainWindow, locale, logger);
} catch (error) {
logger.error('macos/start: error:', getPrintableError(error));
}
}, INTERVAL);
await checkDownloadAndInstall(getMainWindow, messages, logger);
await checkDownloadAndInstall(getMainWindow, locale, logger);
}
let fileName: string;
@ -57,7 +57,7 @@ let loggerForQuitHandler: LoggerType;
async function checkDownloadAndInstall(
getMainWindow: () => BrowserWindow,
messages: MessagesType,
locale: LocaleType,
logger: LoggerType
) {
if (isChecking) {
@ -98,12 +98,12 @@ async function checkDownloadAndInstall(
const message: string = error.message || '';
if (message.includes(readOnly)) {
logger.info('checkDownloadAndInstall: showing read-only dialog...');
showReadOnlyDialog(getMainWindow(), messages);
showReadOnlyDialog(getMainWindow(), locale);
} else {
logger.info(
'checkDownloadAndInstall: showing general update failure dialog...'
);
showCannotUpdateDialog(getMainWindow(), messages);
showCannotUpdateDialog(getMainWindow(), locale);
}
throw error;
@ -114,7 +114,7 @@ async function checkDownloadAndInstall(
logger.info('checkDownloadAndInstall: showing update dialog...');
showUpdateDialog(getMainWindow(), messages, () => {
showUpdateDialog(getMainWindow(), locale, () => {
logger.info('checkDownloadAndInstall: calling quitAndInstall...');
markShouldQuit();
autoUpdater.quitAndInstall();
@ -341,7 +341,7 @@ function shutdown(
export function showReadOnlyDialog(
mainWindow: BrowserWindow,
messages: MessagesType
locale: LocaleType
): void {
let ack = false;
@ -353,20 +353,20 @@ export function showReadOnlyDialog(
setTimeout(async () => {
if (!ack) {
await showFallbackReadOnlyDialog(mainWindow, messages);
await showFallbackReadOnlyDialog(mainWindow, locale);
}
}, ACK_RENDER_TIMEOUT);
}
async function showFallbackReadOnlyDialog(
mainWindow: BrowserWindow,
messages: MessagesType
locale: LocaleType
) {
const options = {
type: 'warning',
buttons: [messages.ok.message],
title: messages.cannotUpdate.message,
message: messages.readOnlyVolume.message,
buttons: [locale.messages.ok.message],
title: locale.messages.cannotUpdate.message,
message: locale.i18n('readOnlyVolume', ['Signal.app', '/Applications']),
};
await dialog.showMessageBox(mainWindow, options);

View file

@ -12,8 +12,8 @@ import {
deleteTempDir,
downloadUpdate,
getPrintableError,
LocaleType,
LoggerType,
MessagesType,
showCannotUpdateDialog,
showUpdateDialog,
} from './common';
@ -30,7 +30,7 @@ const INTERVAL = MINUTE * 30;
export async function start(
getMainWindow: () => BrowserWindow,
messages: MessagesType,
locale: LocaleType,
logger: LoggerType
) {
logger.info('windows/start: starting checks...');
@ -40,14 +40,14 @@ export async function start(
setInterval(async () => {
try {
await checkDownloadAndInstall(getMainWindow, messages, logger);
await checkDownloadAndInstall(getMainWindow, locale, logger);
} catch (error) {
logger.error('windows/start: error:', getPrintableError(error));
}
}, INTERVAL);
await deletePreviousInstallers(logger);
await checkDownloadAndInstall(getMainWindow, messages, logger);
await checkDownloadAndInstall(getMainWindow, locale, logger);
}
let fileName: string;
@ -58,7 +58,7 @@ let loggerForQuitHandler: LoggerType;
async function checkDownloadAndInstall(
getMainWindow: () => BrowserWindow,
messages: MessagesType,
locale: LocaleType,
logger: LoggerType
) {
if (isChecking) {
@ -93,7 +93,7 @@ async function checkDownloadAndInstall(
}
logger.info('checkDownloadAndInstall: showing dialog...');
showUpdateDialog(getMainWindow(), messages, async () => {
showUpdateDialog(getMainWindow(), locale, async () => {
try {
await verifyAndInstall(updateFilePath, version, logger);
installing = true;
@ -101,7 +101,7 @@ async function checkDownloadAndInstall(
logger.info(
'checkDownloadAndInstall: showing general update failure dialog...'
);
showCannotUpdateDialog(getMainWindow(), messages);
showCannotUpdateDialog(getMainWindow(), locale);
throw error;
}

View file

@ -3,7 +3,7 @@
"rule": "jQuery-load(",
"path": "app/locale.js",
"line": "function load({ appLocale, logger } = {}) {",
"lineNumber": 27,
"lineNumber": 28,
"reasonCategory": "falseMatch",
"updated": "2018-09-13T21:20:44.234Z"
},