2020-10-30 20:34:04 +00:00
|
|
|
// Copyright 2018-2020 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2021-10-26 19:15:33 +00:00
|
|
|
import type { LocaleMessagesType } from '../types/I18N';
|
|
|
|
import type { LocalizerType } from '../types/Util';
|
2021-10-01 18:49:59 +00:00
|
|
|
import * as log from '../logging/log';
|
2020-07-29 23:20:05 +00:00
|
|
|
|
2021-09-18 00:30:08 +00:00
|
|
|
export function setupI18n(
|
|
|
|
locale: string,
|
|
|
|
messages: LocaleMessagesType
|
|
|
|
): LocalizerType {
|
2018-03-24 01:37:32 +00:00
|
|
|
if (!locale) {
|
|
|
|
throw new Error('i18n: locale parameter is required');
|
|
|
|
}
|
|
|
|
if (!messages) {
|
|
|
|
throw new Error('i18n: messages parameter is required');
|
|
|
|
}
|
2017-05-15 21:48:19 +00:00
|
|
|
|
2021-09-18 00:30:08 +00:00
|
|
|
const getMessage: LocalizerType = (key, substitutions) => {
|
2018-03-24 01:37:32 +00:00
|
|
|
const entry = messages[key];
|
|
|
|
if (!entry) {
|
2018-07-21 19:00:08 +00:00
|
|
|
log.error(
|
2018-04-27 21:25:04 +00:00
|
|
|
`i18n: Attempted to get translation for nonexistent key '${key}'`
|
|
|
|
);
|
2018-03-24 01:37:32 +00:00
|
|
|
return '';
|
|
|
|
}
|
2020-07-29 23:20:05 +00:00
|
|
|
if (Array.isArray(substitutions) && substitutions.length > 1) {
|
|
|
|
throw new Error(
|
|
|
|
'Array syntax is not supported with more than one placeholder'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
typeof substitutions === 'string' ||
|
|
|
|
typeof substitutions === 'number'
|
|
|
|
) {
|
|
|
|
throw new Error('You must provide either a map or an array');
|
|
|
|
}
|
2017-04-04 06:32:46 +00:00
|
|
|
|
2018-03-24 01:37:32 +00:00
|
|
|
const { message } = entry;
|
2020-07-29 23:20:05 +00:00
|
|
|
if (!substitutions) {
|
|
|
|
return message;
|
2020-09-09 00:46:29 +00:00
|
|
|
}
|
|
|
|
if (Array.isArray(substitutions)) {
|
2018-03-24 01:37:32 +00:00
|
|
|
return substitutions.reduce(
|
|
|
|
(result, substitution) => result.replace(/\$.+?\$/, substitution),
|
|
|
|
message
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-07-29 23:20:05 +00:00
|
|
|
const FIND_REPLACEMENTS = /\$([^$]+)\$/g;
|
|
|
|
|
|
|
|
let match = FIND_REPLACEMENTS.exec(message);
|
|
|
|
let builder = '';
|
|
|
|
let lastTextIndex = 0;
|
|
|
|
|
|
|
|
while (match) {
|
|
|
|
if (lastTextIndex < match.index) {
|
|
|
|
builder += message.slice(lastTextIndex, match.index);
|
|
|
|
}
|
|
|
|
|
|
|
|
const placeholderName = match[1];
|
|
|
|
const value = substitutions[placeholderName];
|
|
|
|
if (!value) {
|
|
|
|
log.error(
|
|
|
|
`i18n: Value not provided for placeholder ${placeholderName} in key '${key}'`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
builder += value || '';
|
|
|
|
|
|
|
|
lastTextIndex = FIND_REPLACEMENTS.lastIndex;
|
|
|
|
match = FIND_REPLACEMENTS.exec(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastTextIndex < message.length) {
|
|
|
|
builder += message.slice(lastTextIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
return builder;
|
2021-09-18 00:30:08 +00:00
|
|
|
};
|
2018-03-24 01:37:32 +00:00
|
|
|
|
|
|
|
getMessage.getLocale = () => locale;
|
|
|
|
|
|
|
|
return getMessage;
|
2021-09-18 00:30:08 +00:00
|
|
|
}
|