Fix timestamps/spellcheck to use locale override

This commit is contained in:
Jamie Kyle 2023-11-06 17:02:13 -08:00 committed by GitHub
parent 59fa75c309
commit fd8691b871
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 45 additions and 11 deletions

View file

@ -110,6 +110,7 @@ window.SignalContext = {
getHourCyclePreference: () => HourCyclePreference.UnknownPreference, getHourCyclePreference: () => HourCyclePreference.UnknownPreference,
getPreferredSystemLocales: () => ['en'], getPreferredSystemLocales: () => ['en'],
getResolvedMessagesLocaleDirection: () => 'ltr', getResolvedMessagesLocaleDirection: () => 'ltr',
getLocaleOverride: () => null,
}; };
window.i18n = i18n; window.i18n = i18n;

View file

@ -143,6 +143,7 @@ const consoleLogger = createBufferedConsoleLogger();
// These will be set after app fires the 'ready' event // These will be set after app fires the 'ready' event
let logger: LoggerType | undefined; let logger: LoggerType | undefined;
let preferredSystemLocales: Array<string> | undefined; let preferredSystemLocales: Array<string> | undefined;
let localeOverride: string | null | undefined;
let resolvedTranslationsLocale: LocaleType | undefined; let resolvedTranslationsLocale: LocaleType | undefined;
let settingsChannel: SettingsChannel | undefined; let settingsChannel: SettingsChannel | undefined;
@ -431,6 +432,13 @@ function getPreferredSystemLocales(): Array<string> {
return preferredSystemLocales; return preferredSystemLocales;
} }
function getLocaleOverride(): string | null {
if (typeof localeOverride === 'undefined') {
throw new Error('getLocaleOverride: Locale not yet initialized!');
}
return localeOverride;
}
function getResolvedMessagesLocale(): LocaleType { function getResolvedMessagesLocale(): LocaleType {
if (!resolvedTranslationsLocale) { if (!resolvedTranslationsLocale) {
throw new Error('getResolvedMessagesLocale: Locale not yet initialized!'); throw new Error('getResolvedMessagesLocale: Locale not yet initialized!');
@ -824,6 +832,7 @@ async function createWindow() {
setupSpellChecker( setupSpellChecker(
mainWindow, mainWindow,
getPreferredSystemLocales(), getPreferredSystemLocales(),
getLocaleOverride(),
getResolvedMessagesLocale().i18n, getResolvedMessagesLocale().i18n,
getLogger() getLogger()
); );
@ -1809,7 +1818,7 @@ app.on('ready', async () => {
loadPreferredSystemLocales() loadPreferredSystemLocales()
); );
const localeOverride = await getLocaleOverrideSetting(); localeOverride = await getLocaleOverrideSetting();
const hourCyclePreference = getHourCyclePreference(); const hourCyclePreference = getHourCyclePreference();
logger.info(`app.ready: hour cycle preference: ${hourCyclePreference}`); logger.info(`app.ready: hour cycle preference: ${hourCyclePreference}`);
@ -2400,6 +2409,7 @@ ipc.on('get-config', async event => {
resolvedTranslationsLocaleDirection: getResolvedMessagesLocale().direction, resolvedTranslationsLocaleDirection: getResolvedMessagesLocale().direction,
hourCyclePreference: getResolvedMessagesLocale().hourCyclePreference, hourCyclePreference: getResolvedMessagesLocale().hourCyclePreference,
preferredSystemLocales: getPreferredSystemLocales(), preferredSystemLocales: getPreferredSystemLocales(),
localeOverride: getLocaleOverride(),
version: app.getVersion(), version: app.getVersion(),
buildCreation: config.get<number>('buildCreation'), buildCreation: config.get<number>('buildCreation'),
buildExpiration: config.get<number>('buildExpiration'), buildExpiration: config.get<number>('buildExpiration'),

View file

@ -56,6 +56,7 @@ export function getLanguages(
export const setup = ( export const setup = (
browserWindow: BrowserWindow, browserWindow: BrowserWindow,
preferredSystemLocales: ReadonlyArray<string>, preferredSystemLocales: ReadonlyArray<string>,
localeOverride: string | null,
i18n: LocalizerType, i18n: LocalizerType,
logger: LoggerType logger: LoggerType
): void => { ): void => {
@ -74,13 +75,16 @@ export const setup = (
logger.info('spellcheck: dictionary initialized:', lang); logger.info('spellcheck: dictionary initialized:', lang);
}); });
// Locale override should be combined with other preferences rather than
// replace them entirely.
const combinedLocales =
localeOverride != null
? [localeOverride, ...preferredSystemLocales]
: preferredSystemLocales;
const availableLocales = session.availableSpellCheckerLanguages; const availableLocales = session.availableSpellCheckerLanguages;
const languages = getLanguages( const languages = getLanguages(combinedLocales, availableLocales, 'en');
preferredSystemLocales, console.log('spellcheck: user locales:', combinedLocales);
availableLocales,
'en'
);
console.log('spellcheck: user locales:', preferredSystemLocales);
console.log( console.log(
'spellcheck: available spellchecker languages:', 'spellcheck: available spellchecker languages:',
availableLocales availableLocales

View file

@ -33,6 +33,7 @@ global.window = {
getResolvedMessagesLocaleDirection: () => 'ltr', getResolvedMessagesLocaleDirection: () => 'ltr',
getHourCyclePreference: () => HourCyclePreference.UnknownPreference, getHourCyclePreference: () => HourCyclePreference.UnknownPreference,
getPreferredSystemLocales: () => ['en'], getPreferredSystemLocales: () => ['en'],
getLocaleOverride: () => null,
}, },
i18n: key => `i18n(${key})`, i18n: key => `i18n(${key})`,
storage: { storage: {

View file

@ -60,3 +60,4 @@ window.textsecure.storage.protocol = window.getSignalProtocolStore();
})(); })();
window.getPreferredSystemLocales = () => ['en']; window.getPreferredSystemLocales = () => ['en'];
window.getLocaleOverride = () => null;

View file

@ -12,6 +12,7 @@ const max = new Date(2023, 0, 1, 23).getTime();
describe('formatTimestamp', () => { describe('formatTimestamp', () => {
let sandbox: sinon.SinonSandbox; let sandbox: sinon.SinonSandbox;
let localesStub: sinon.SinonStub; let localesStub: sinon.SinonStub;
let localeOverrideStub: sinon.SinonStub;
let hourCycleStub: sinon.SinonStub; let hourCycleStub: sinon.SinonStub;
beforeEach(() => { beforeEach(() => {
@ -20,6 +21,10 @@ describe('formatTimestamp', () => {
window.SignalContext, window.SignalContext,
'getPreferredSystemLocales' 'getPreferredSystemLocales'
); );
localeOverrideStub = sandbox.stub(
window.SignalContext,
'getLocaleOverride'
);
hourCycleStub = sandbox.stub( hourCycleStub = sandbox.stub(
window.SignalContext, window.SignalContext,
'getHourCyclePreference' 'getHourCyclePreference'
@ -41,6 +46,7 @@ describe('formatTimestamp', () => {
}).format(time); }).format(time);
it(`should format with locale: ${locale} (${HourCyclePreference[preference]}) @ ${timeFmt})`, () => { it(`should format with locale: ${locale} (${HourCyclePreference[preference]}) @ ${timeFmt})`, () => {
localesStub.returns([locale]); localesStub.returns([locale]);
localeOverrideStub.returns(null);
hourCycleStub.returns(preference); hourCycleStub.returns(preference);
assert.equal(formatTimestamp(time, { timeStyle: 'medium' }), expected); assert.equal(formatTimestamp(time, { timeStyle: 'medium' }), expected);
}); });

View file

@ -51,6 +51,7 @@ export const rendererConfigSchema = z.object({
resolvedTranslationsLocaleDirection: z.enum(['ltr', 'rtl']), resolvedTranslationsLocaleDirection: z.enum(['ltr', 'rtl']),
hourCyclePreference: HourCyclePreferenceSchema, hourCyclePreference: HourCyclePreferenceSchema,
preferredSystemLocales: z.array(configRequiredStringSchema), preferredSystemLocales: z.array(configRequiredStringSchema),
localeOverride: z.string().nullable(),
name: configRequiredStringSchema, name: configRequiredStringSchema,
nodeVersion: configRequiredStringSchema, nodeVersion: configRequiredStringSchema,
proxyUrl: configOptionalStringSchema, proxyUrl: configOptionalStringSchema,

View file

@ -67,7 +67,11 @@ const formatterCache = new Map<string, Intl.DateTimeFormat>();
export function getDateTimeFormatter( export function getDateTimeFormatter(
options: Intl.DateTimeFormatOptions options: Intl.DateTimeFormatOptions
): Intl.DateTimeFormat { ): Intl.DateTimeFormat {
const locales = window.SignalContext.getPreferredSystemLocales(); const preferredSystemLocales =
window.SignalContext.getPreferredSystemLocales();
const localeOverride = window.SignalContext.getLocaleOverride();
const locales =
localeOverride != null ? [localeOverride] : preferredSystemLocales;
const optionsWithPreferences = getOptionsWithPreferences(options); const optionsWithPreferences = getOptionsWithPreferences(options);
const cacheKey = getCacheKey(locales, optionsWithPreferences); const cacheKey = getCacheKey(locales, optionsWithPreferences);
const cachedFormatter = formatterCache.get(cacheKey); const cachedFormatter = formatterCache.get(cacheKey);

View file

@ -48,6 +48,7 @@ export type MinimalSignalContextType = {
getHourCyclePreference: () => HourCyclePreference; getHourCyclePreference: () => HourCyclePreference;
getResolvedMessagesLocale: () => string; getResolvedMessagesLocale: () => string;
getPreferredSystemLocales: () => Array<string>; getPreferredSystemLocales: () => Array<string>;
getLocaleOverride: () => string | null;
getMainWindowStats: () => Promise<MainWindowStatsType>; getMainWindowStats: () => Promise<MainWindowStatsType>;
getMenuOptions: () => Promise<MenuOptionsType>; getMenuOptions: () => Promise<MenuOptionsType>;
getNodeVersion: () => string; getNodeVersion: () => string;

View file

@ -45,15 +45,19 @@ window.libphonenumberFormat = PhoneNumberFormat;
window.React = React; window.React = React;
window.ReactDOM = ReactDOM; window.ReactDOM = ReactDOM;
const { resolvedTranslationsLocale, preferredSystemLocales } = config; const { resolvedTranslationsLocale, preferredSystemLocales, localeOverride } =
moment.updateLocale(resolvedTranslationsLocale, { config;
moment.updateLocale(localeOverride ?? resolvedTranslationsLocale, {
relativeTime: { relativeTime: {
s: window.i18n('icu:timestamp_s'), s: window.i18n('icu:timestamp_s'),
m: window.i18n('icu:timestamp_m'), m: window.i18n('icu:timestamp_m'),
h: window.i18n('icu:timestamp_h'), h: window.i18n('icu:timestamp_h'),
}, },
}); });
moment.locale(preferredSystemLocales); moment.locale(
localeOverride != null ? [localeOverride] : preferredSystemLocales
);
const userDataPath = SignalContext.getPath('userData'); const userDataPath = SignalContext.getPath('userData');
window.BasePaths = { window.BasePaths = {

View file

@ -49,6 +49,7 @@ export const MinimalSignalContext: MinimalSignalContextType = {
config.resolvedTranslationsLocaleDirection, config.resolvedTranslationsLocaleDirection,
getHourCyclePreference: () => config.hourCyclePreference, getHourCyclePreference: () => config.hourCyclePreference,
getPreferredSystemLocales: () => config.preferredSystemLocales, getPreferredSystemLocales: () => config.preferredSystemLocales,
getLocaleOverride: () => config.localeOverride,
nativeThemeListener: createNativeThemeListener(ipcRenderer, window), nativeThemeListener: createNativeThemeListener(ipcRenderer, window),
restartApp: () => ipcRenderer.send('restart'), restartApp: () => ipcRenderer.send('restart'),
OS: { OS: {