Skip to content

Commit

Permalink
Use preferred system locales and add Farsi font stack
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiebuilds-signal committed Jan 25, 2023
1 parent fbdfaf3 commit da0a741
Show file tree
Hide file tree
Showing 14 changed files with 125 additions and 73 deletions.
51 changes: 26 additions & 25 deletions app/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ function finalize(
}

export function load({
appLocale,
preferredSystemLocales,
logger,
}: {
appLocale: string;
logger: Pick<LoggerType, 'error' | 'warn'>;
preferredSystemLocales: Array<string>;
logger: Pick<LoggerType, 'error' | 'warn' | 'info'>;
}): LocaleType {
if (!appLocale) {
if (preferredSystemLocales.length === 0) {
throw new TypeError('`appLocale` is required');
}

Expand All @@ -68,27 +68,28 @@ export function load({

const english = getLocaleMessages('en');

// Load locale - if we can't load messages for the current locale, we
// default to 'en'
//
// possible locales:
// https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc
const languageOnly = removeRegion(appLocale);

try {
return finalize(getLocaleMessages(appLocale), english, appLocale);
} catch (e) {
logger.warn(`Problem loading messages for locale ${appLocale}`);
for (const locale of preferredSystemLocales) {
try {
logger.info(`Loading preferred system locale: '${locale}'`);
return finalize(getLocaleMessages(locale), english, locale);
} catch (e) {
logger.warn(
`Problem loading messages for locale '${locale}', ${e.toString()}`
);
}

const languageOnly = removeRegion(locale);
try {
logger.warn(`Falling back to parent language: '${languageOnly}'`);
// Note: messages are from parent language, but we still keep the region
return finalize(getLocaleMessages(languageOnly), english, locale);
} catch (e) {
logger.error(
`Problem loading messages for parent locale '${languageOnly}'`
);
}
}

try {
logger.warn(`Falling back to parent language: '${languageOnly}'`);
// Note: messages are from parent language, but we still keep the region
return finalize(getLocaleMessages(languageOnly), english, appLocale);
} catch (e) {
logger.error(`Problem loading messages for locale ${languageOnly}`);

logger.warn("Falling back to 'en' locale");
return finalize(english, english, 'en');
}
logger.warn("Falling back to 'en' locale");
return finalize(english, english, 'en');
}
88 changes: 59 additions & 29 deletions app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ let menuOptions: CreateTemplateOptionsType | undefined;

// These will be set after app fires the 'ready' event
let logger: LoggerType | undefined;
let locale: LocaleType | undefined;
let preferredSystemLocales: Array<string> | undefined;
let resolvedTranslationsLocale: LocaleType | undefined;
let settingsChannel: SettingsChannel | undefined;

function getLogger(): LoggerType {
Expand All @@ -364,12 +365,19 @@ function getLogger(): LoggerType {
return logger;
}

function getLocale(): LocaleType {
if (!locale) {
throw new Error('getLocale: Locale not yet initialized!');
function getPreferredSystemLocales(): Array<string> {
if (!preferredSystemLocales) {
throw new Error('getPreferredSystemLocales: Locales not yet initialized!');
}
return preferredSystemLocales;
}

function getResolvedMessagesLocale(): LocaleType {
if (!resolvedTranslationsLocale) {
throw new Error('getResolvedMessagesLocale: Locale not yet initialized!');
}

return locale;
return resolvedTranslationsLocale;
}

type PrepareUrlOptions = { forCalling?: boolean; forCamera?: boolean };
Expand Down Expand Up @@ -404,7 +412,8 @@ async function prepareUrl(

const urlParams: RendererConfigType = {
name: packageJson.productName,
locale: getLocale().name,
resolvedTranslationsLocale: getResolvedMessagesLocale().name,
preferredSystemLocales: getPreferredSystemLocales(),
version: app.getVersion(),
buildCreation: config.get<number>('buildCreation'),
buildExpiration: config.get<number>('buildExpiration'),
Expand Down Expand Up @@ -750,7 +759,7 @@ async function createWindow() {
}

mainWindowCreated = true;
setupSpellChecker(mainWindow, getLocale());
setupSpellChecker(mainWindow, getResolvedMessagesLocale());
if (!startInTray && windowConfig && windowConfig.maximized) {
mainWindow.maximize();
}
Expand Down Expand Up @@ -879,8 +888,12 @@ async function createWindow() {
getLogger().info('close: showing tray notice');

const n = new Notification({
title: getLocale().i18n('minimizeToTrayNotification--title'),
body: getLocale().i18n('minimizeToTrayNotification--body'),
title: getResolvedMessagesLocale().i18n(
'minimizeToTrayNotification--title'
),
body: getResolvedMessagesLocale().i18n(
'minimizeToTrayNotification--body'
),
});

n.show();
Expand Down Expand Up @@ -1143,7 +1156,7 @@ async function showScreenShareWindow(sourceName: string) {
minimizable: false,
resizable: false,
show: false,
title: getLocale().i18n('screenShareWindow'),
title: getResolvedMessagesLocale().i18n('screenShareWindow'),
titleBarStyle: nonMainTitleBarStyle,
width,
webPreferences: {
Expand Down Expand Up @@ -1194,7 +1207,7 @@ async function showAbout() {
width: 500,
height: 500,
resizable: false,
title: getLocale().i18n('aboutSignalDesktop'),
title: getResolvedMessagesLocale().i18n('aboutSignalDesktop'),
titleBarStyle: nonMainTitleBarStyle,
titleBarOverlay,
autoHideMenuBar: true,
Expand Down Expand Up @@ -1242,7 +1255,7 @@ async function showSettingsWindow() {
height: 700,
frame: true,
resizable: false,
title: getLocale().i18n('signalDesktopPreferences'),
title: getResolvedMessagesLocale().i18n('signalDesktopPreferences'),
titleBarStyle: nonMainTitleBarStyle,
titleBarOverlay,
autoHideMenuBar: true,
Expand Down Expand Up @@ -1294,7 +1307,9 @@ async function getIsLinked() {
let stickerCreatorWindow: BrowserWindow | undefined;
async function showStickerCreator() {
if (!(await getIsLinked())) {
const message = getLocale().i18n('StickerCreator--Authentication--error');
const message = getResolvedMessagesLocale().i18n(
'StickerCreator--Authentication--error'
);

await dialog.showMessageBox({
type: 'warning',
Expand All @@ -1319,7 +1334,7 @@ async function showStickerCreator() {
width: 800,
minWidth: 800,
height: 650,
title: getLocale().i18n('signalDesktopStickerCreator'),
title: getResolvedMessagesLocale().i18n('signalDesktopStickerCreator'),
titleBarStyle: nonMainTitleBarStyle,
titleBarOverlay,
autoHideMenuBar: true,
Expand All @@ -1338,7 +1353,7 @@ async function showStickerCreator() {
};

stickerCreatorWindow = new BrowserWindow(options);
setupSpellChecker(stickerCreatorWindow, getLocale());
setupSpellChecker(stickerCreatorWindow, getResolvedMessagesLocale());

handleCommonWindowEvents(stickerCreatorWindow, titleBarOverlay);

Expand Down Expand Up @@ -1381,7 +1396,7 @@ async function showDebugLogWindow() {
width: 700,
height: 500,
resizable: false,
title: getLocale().i18n('debugLog'),
title: getResolvedMessagesLocale().i18n('debugLog'),
titleBarStyle: nonMainTitleBarStyle,
titleBarOverlay,
autoHideMenuBar: true,
Expand Down Expand Up @@ -1445,7 +1460,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
width: Math.min(400, size[0]),
height: Math.min(150, size[1]),
resizable: false,
title: getLocale().i18n('allowAccess'),
title: getResolvedMessagesLocale().i18n('allowAccess'),
titleBarStyle: nonMainTitleBarStyle,
autoHideMenuBar: true,
backgroundColor: await getBackgroundColor(),
Expand Down Expand Up @@ -1567,13 +1582,13 @@ const onDatabaseError = async (error: string) => {

const buttonIndex = dialog.showMessageBoxSync({
buttons: [
getLocale().i18n('deleteAndRestart'),
getLocale().i18n('copyErrorAndQuit'),
getResolvedMessagesLocale().i18n('deleteAndRestart'),
getResolvedMessagesLocale().i18n('copyErrorAndQuit'),
],
defaultId: 1,
cancelId: 1,
detail: redactAll(error),
message: getLocale().i18n('databaseError'),
message: getResolvedMessagesLocale().i18n('databaseError'),
noLink: true,
type: 'error',
});
Expand Down Expand Up @@ -1601,8 +1616,10 @@ ipc.on('database-error', (_event: Electron.Event, error: string) => {
drop(onDatabaseError(error));
});

function getAppLocale(): string {
return getEnvironment() === Environment.Test ? 'en' : app.getLocale();
function loadPreferredSystemLocales(): Array<string> {
return getEnvironment() === Environment.Test
? ['en']
: app.getPreferredSystemLanguages();
}

async function getDefaultLoginItemSettings(): Promise<LoginItemSettingsOptions> {
Expand Down Expand Up @@ -1654,9 +1671,17 @@ app.on('ready', async () => {

await setupCrashReports(getLogger);

if (!locale) {
const appLocale = getAppLocale();
locale = loadLocale({ appLocale, logger: getLogger() });
if (!resolvedTranslationsLocale) {
preferredSystemLocales = loadPreferredSystemLocales();
logger.info(
`app.ready: preferred system locales: ${preferredSystemLocales.join(
', '
)}}`
);
resolvedTranslationsLocale = loadLocale({
preferredSystemLocales,
logger: getLogger(),
});
}

sqlInitPromise = initializeSQL(userDataPath);
Expand Down Expand Up @@ -1762,7 +1787,7 @@ app.on('ready', async () => {
);
}

GlobalErrors.updateLocale(locale);
GlobalErrors.updateLocale(resolvedTranslationsLocale);

// If the sql initialization takes more than three seconds to complete, we
// want to notify the user that things are happening
Expand Down Expand Up @@ -1877,7 +1902,9 @@ app.on('ready', async () => {

setupMenu();

systemTrayService = new SystemTrayService({ i18n: locale.i18n });
systemTrayService = new SystemTrayService({
i18n: resolvedTranslationsLocale.i18n,
});
systemTrayService.setMainWindow(mainWindow);
systemTrayService.setEnabled(
shouldMinimizeToSystemTray(await systemTraySettingCache.get())
Expand Down Expand Up @@ -1920,7 +1947,10 @@ function setupMenu(options?: Partial<CreateTemplateOptionsType>) {
// overrides
...options,
};
const template = createTemplate(menuOptions, getLocale().i18n);
const template = createTemplate(
menuOptions,
getResolvedMessagesLocale().i18n
);
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);

Expand Down Expand Up @@ -2235,7 +2265,7 @@ ipc.on('get-built-in-images', async () => {
// Ingested in preload.js via a sendSync call
ipc.on('locale-data', event => {
// eslint-disable-next-line no-param-reassign
event.returnValue = getLocale().messages;
event.returnValue = getResolvedMessagesLocale().messages;
});

ipc.on('user-config-key', event => {
Expand Down
5 changes: 4 additions & 1 deletion sticker-creator/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ function ColdRoot() {
return (
<ReduxProvider store={store}>
<Router history={history}>
<I18n messages={localeMessages} locale={SignalContext.config.locale}>
<I18n
messages={localeMessages}
locale={SignalContext.config.resolvedTranslationsLocale}
>
<App
executeMenuRole={SignalContext.executeMenuRole}
hasCustomTitleBar={SignalContext.OS.hasCustomTitleBar()}
Expand Down
6 changes: 6 additions & 0 deletions stylesheets/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@

@mixin font-family {
font-family: $inter;
/* Japanese */
&:lang(ja) {
font-family: 'SF Pro JP', 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3',
メイリオ, Meiryo, 'MS Pゴシック', 'Helvetica Neue', Helvetica, Arial,
sans-serif;
}
/* Farsi (Persian) */
&:lang(fa) {
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
Tahoma, 'Noto Sans Arabic', Helvetica, Arial, sans-serif;
}
}

@mixin font-title-1 {
Expand Down
2 changes: 1 addition & 1 deletion ts/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ export async function startApp(): Promise<void> {

document.documentElement.setAttribute(
'lang',
window.getLocale().substring(0, 2)
window.getResolvedMessagesLocale().split(/[-_]/)[0]
);

KeyChangeListener.init(window.textsecure.storage.protocol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function ChatSessionRefreshedNotification(

const baseUrl =
'https://support.signal.org/hc/LOCALE/requests/new?desktop&chat_refreshed';
const locale = window.getLocale();
const locale = window.getResolvedMessagesLocale();
const supportLocale = mapToSupportLocale(locale);
const url = baseUrl.replace('LOCALE', supportLocale);

Expand Down
4 changes: 2 additions & 2 deletions ts/models/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2961,8 +2961,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
'getProfile: expected updatesUrl to be a defined string'
);
const userLanguages = getUserLanguages(
navigator.languages,
window.getLocale()
window.getPreferredSystemLocales(),
window.getResolvedMessagesLocale()
);
const { messaging } = window.textsecure;
if (!messaging) {
Expand Down
4 changes: 2 additions & 2 deletions ts/services/profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ async function doGetProfile(c: ConversationModel): Promise<void> {
);

const userLanguages = getUserLanguages(
navigator.languages,
window.getLocale()
window.getPreferredSystemLocales(),
window.getResolvedMessagesLocale()
);

let profile;
Expand Down
5 changes: 4 additions & 1 deletion ts/test-node/app/menu_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,11 @@ const PLATFORMS = [

describe('createTemplate', () => {
const { i18n } = loadLocale({
appLocale: 'en',
preferredSystemLocales: ['en'],
logger: {
info(_arg: unknown) {
// noop
},
error(arg: unknown) {
throw new Error(String(arg));
},
Expand Down
3 changes: 2 additions & 1 deletion ts/types/RendererConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export const rendererConfigSchema = z.object({
environment: environmentSchema,
homePath: configRequiredStringSchema,
hostname: configRequiredStringSchema,
locale: configRequiredStringSchema,
resolvedTranslationsLocale: configRequiredStringSchema,
preferredSystemLocales: z.array(configRequiredStringSchema),
name: configRequiredStringSchema,
nodeVersion: configRequiredStringSchema,
proxyUrl: configOptionalStringSchema,
Expand Down

0 comments on commit da0a741

Please sign in to comment.