Add bidi strip setting and use in os dialogs
This commit is contained in:
parent
a710f09977
commit
07195f4096
5 changed files with 32 additions and 15 deletions
|
@ -1676,6 +1676,7 @@ async function initializeSQL(
|
||||||
userDataPath: string
|
userDataPath: string
|
||||||
): Promise<{ ok: true; error: undefined } | { ok: false; error: Error }> {
|
): Promise<{ ok: true; error: undefined } | { ok: false; error: Error }> {
|
||||||
sqlInitTimeStart = Date.now();
|
sqlInitTimeStart = Date.now();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This should be the first awaited call in this function, otherwise
|
// This should be the first awaited call in this function, otherwise
|
||||||
// `sql.sqlCall` will throw an uninitialized error instead of waiting for
|
// `sql.sqlCall` will throw an uninitialized error instead of waiting for
|
||||||
|
@ -1732,9 +1733,11 @@ const onDatabaseError = async (error: string) => {
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, this is some other kind of DB error, let's give them the option to
|
// Otherwise, this is some other kind of DB error, let's give them the option to
|
||||||
// delete.
|
// delete.
|
||||||
messageDetail = i18n('icu:databaseError__detail', {
|
messageDetail = i18n(
|
||||||
link: SIGNAL_SUPPORT_LINK,
|
'icu:databaseError__detail',
|
||||||
});
|
{ link: SIGNAL_SUPPORT_LINK },
|
||||||
|
{ bidi: 'strip' }
|
||||||
|
);
|
||||||
|
|
||||||
buttons.push(i18n('icu:deleteAndRestart'));
|
buttons.push(i18n('icu:deleteAndRestart'));
|
||||||
deleteAllDataButtonIndex = 1;
|
deleteAllDataButtonIndex = 1;
|
||||||
|
|
|
@ -673,10 +673,8 @@ function showShareCallLinkViaSignal(
|
||||||
],
|
],
|
||||||
messageBody: i18n(
|
messageBody: i18n(
|
||||||
'icu:ShareCallLinkViaSignal__DraftMessageText',
|
'icu:ShareCallLinkViaSignal__DraftMessageText',
|
||||||
{
|
{ url },
|
||||||
url,
|
{ bidi: 'strip' }
|
||||||
},
|
|
||||||
{ textIsBidiFreeSkipNormalization: true }
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,7 +24,13 @@ export type RenderTextCallbackType = (options: {
|
||||||
export { ICUJSXMessageParamsByKeyType, ICUStringMessageParamsByKeyType };
|
export { ICUJSXMessageParamsByKeyType, ICUStringMessageParamsByKeyType };
|
||||||
|
|
||||||
export type LocalizerOptions = {
|
export type LocalizerOptions = {
|
||||||
textIsBidiFreeSkipNormalization?: boolean;
|
/**
|
||||||
|
* - 'default' will fence all string parameters with unicode bidi isolates
|
||||||
|
* and balance the control characters within them
|
||||||
|
* - 'strip' should only be used when all of the parameters are not
|
||||||
|
* user-generated and should not contain any control characters.
|
||||||
|
*/
|
||||||
|
bidi?: 'default' | 'strip';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LocalizerType = {
|
export type LocalizerType = {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { strictAssert } from './assert';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import { Environment, getEnvironment } from '../environment';
|
import { Environment, getEnvironment } from '../environment';
|
||||||
import { bidiIsolate } from './unicodeBidi';
|
import { bidiIsolate, bidiStrip } from './unicodeBidi';
|
||||||
|
|
||||||
export function isLocaleMessageType(
|
export function isLocaleMessageType(
|
||||||
value: unknown
|
value: unknown
|
||||||
|
@ -65,7 +65,10 @@ export function createCachedIntl(
|
||||||
|
|
||||||
function normalizeSubstitutions<
|
function normalizeSubstitutions<
|
||||||
Substitutions extends Record<string, string | number | Date> | undefined
|
Substitutions extends Record<string, string | number | Date> | undefined
|
||||||
>(substitutions?: Substitutions): Substitutions | undefined {
|
>(
|
||||||
|
substitutions?: Substitutions,
|
||||||
|
options?: LocalizerOptions
|
||||||
|
): Substitutions | undefined {
|
||||||
if (!substitutions) {
|
if (!substitutions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +79,11 @@ function normalizeSubstitutions<
|
||||||
}
|
}
|
||||||
for (const [key, value] of entries) {
|
for (const [key, value] of entries) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
normalized[key] = bidiIsolate(value);
|
if (options?.bidi === 'strip') {
|
||||||
|
normalized[key] = bidiStrip(value);
|
||||||
|
} else {
|
||||||
|
normalized[key] = bidiIsolate(value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
normalized[key] = value;
|
normalized[key] = value;
|
||||||
}
|
}
|
||||||
|
@ -123,9 +130,7 @@ export function setupI18n(
|
||||||
) => {
|
) => {
|
||||||
const result = intl.formatMessage(
|
const result = intl.formatMessage(
|
||||||
{ id: key },
|
{ id: key },
|
||||||
options?.textIsBidiFreeSkipNormalization
|
normalizeSubstitutions(substitutions, options)
|
||||||
? substitutions
|
|
||||||
: normalizeSubstitutions(substitutions)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
strictAssert(result !== key, `i18n: missing translation for "${key}"`);
|
strictAssert(result !== key, `i18n: missing translation for "${key}"`);
|
||||||
|
|
|
@ -109,7 +109,8 @@ export const ANY_UNICODE_DIR_CONTROL_CHAR_REGEX = new RegExp(
|
||||||
POP_DIRECTIONAL_FORMATTING,
|
POP_DIRECTIONAL_FORMATTING,
|
||||||
LTR_OVERRIDE,
|
LTR_OVERRIDE,
|
||||||
RTL_OVERRIDE,
|
RTL_OVERRIDE,
|
||||||
].join('|')
|
].join('|'),
|
||||||
|
'g'
|
||||||
);
|
);
|
||||||
|
|
||||||
export function hasAnyUnicodeDirControlChars(input: string): boolean {
|
export function hasAnyUnicodeDirControlChars(input: string): boolean {
|
||||||
|
@ -216,3 +217,7 @@ export function bidiIsolate(text: string): string {
|
||||||
}
|
}
|
||||||
return _bidiIsolate(text);
|
return _bidiIsolate(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function bidiStrip(text: string): string {
|
||||||
|
return text.replace(ANY_UNICODE_DIR_CONTROL_CHAR_REGEX, '');
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue