You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
// this file is a weird one as it is used by both sides of electron at the same time
|
|
|
|
import { isUndefined } from 'lodash';
|
|
import { GetMessageArgs, LocalizerDictionary, LocalizerToken } from '../types/Localizer';
|
|
|
|
/**
|
|
* Logs an i18n message to the console.
|
|
* @param message - The message to log.
|
|
*
|
|
* TODO - Replace this logging method when the new logger is created
|
|
*/
|
|
function i18nLog(message: string) {
|
|
// eslint:disable: no-console
|
|
// eslint-disable-next-line no-console
|
|
(window?.log?.error ?? console.log)(message);
|
|
}
|
|
|
|
/**
|
|
* Sets up the i18n function with the provided locale and messages.
|
|
*
|
|
* @param locale - The locale to use for translations.
|
|
* @param dictionary - A dictionary of localized messages.
|
|
*
|
|
* @returns A function that retrieves a localized message string, substituting variables where necessary.
|
|
*/
|
|
export const setupi18n = (locale: string, dictionary: LocalizerDictionary) => {
|
|
if (!locale) {
|
|
throw new Error('i18n: locale parameter is required');
|
|
}
|
|
if (!dictionary) {
|
|
throw new Error('i18n: messages parameter is required');
|
|
}
|
|
|
|
/**
|
|
* Retrieves a localized message string, substituting variables where necessary.
|
|
*
|
|
* @param token - The token identifying the message to retrieve.
|
|
* @param args - An optional record of substitution variables and their replacement values. This is required if the string has dynamic variables.
|
|
*
|
|
* @returns The localized message string with substitutions applied.
|
|
*
|
|
* @example
|
|
* // The string greeting is 'Hello, {name}!' in the current locale
|
|
* window.i18n('greeting', { name: 'Alice' });
|
|
* // => 'Hello, Alice!'
|
|
*/
|
|
function getMessage<T extends LocalizerToken, R extends LocalizerDictionary[T]>(
|
|
...[token, args]: GetMessageArgs<T>
|
|
): R {
|
|
const localizedString = dictionary[token];
|
|
|
|
if (!localizedString) {
|
|
i18nLog(`i18n: Attempted to get translation for nonexistent key '${token}'`);
|
|
return '' as R;
|
|
}
|
|
|
|
/** If a localized string does not have any arguments to substitute it is retured with no changes */
|
|
if (!args) {
|
|
return localizedString as R;
|
|
}
|
|
|
|
/** Find and replace the dynamic variables in a localized string and substitute the variables with the provided values */
|
|
return localizedString.replace(/\{(\w+)\}/g, (match, arg: keyof typeof args) => {
|
|
const substitution = args[arg];
|
|
/** If a substitution is undefined we return the variable match */
|
|
return isUndefined(substitution) ? match : substitution.toString();
|
|
}) as R;
|
|
}
|
|
|
|
getMessage.getLocale = () => locale;
|
|
|
|
return getMessage;
|
|
};
|
|
|
|
// eslint-disable-next-line import/no-mutable-exports
|
|
export let langNotSupportedMessageShown = false;
|
|
|
|
export const loadEmojiPanelI18n = async () => {
|
|
if (!window) {
|
|
return undefined;
|
|
}
|
|
|
|
const lang = (window.i18n as any).getLocale();
|
|
if (lang !== 'en') {
|
|
try {
|
|
const langData = await import(`@emoji-mart/data/i18n/${lang}.json`);
|
|
return langData;
|
|
} catch (err) {
|
|
if (!langNotSupportedMessageShown) {
|
|
window?.log?.warn(
|
|
'Language is not supported by emoji-mart package. See https://github.com/missive/emoji-mart/tree/main/packages/emoji-mart-data/i18n'
|
|
);
|
|
langNotSupportedMessageShown = true;
|
|
}
|
|
}
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
// RTL Support
|
|
|
|
export type HTMLDirection = 'ltr' | 'rtl';
|
|
|
|
export function isRtlBody(): boolean {
|
|
const body = document.getElementsByTagName('body').item(0);
|
|
|
|
return body?.classList.contains('rtl') || false;
|
|
}
|
|
|
|
export const useHTMLDirection = (): HTMLDirection => (isRtlBody() ? 'rtl' : 'ltr');
|