openstamanager/resources/ts/utils/i18n.ts

81 lines
2.8 KiB
TypeScript
Raw Normal View History

// noinspection FunctionNamingConventionJS
import {Vnode} from 'mithril';
export type ReplaceObject = Record<string, string | Vnode | number | boolean>;
2023-05-05 01:17:47 +02:00
export type Localized<B> = (B extends true ? string : Vnode<any, any>);
/**
* @member {string} key String to translate.
*/
export interface TranslationParameters<B extends boolean | undefined> {
replace?: ReplaceObject;
forceString?: B;
}
/**
* Get a Vnode containing the translated string.
*
* @param {string} key String to translate.
* @param {?ReplaceObject} replace Object containing the parameters to replace in the string.
* @param {boolean} forceString Whether to force the return value to be a string.
*
* @returns {string} String with replaced parameters if forceString is .
*
* @protected
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export function tr<B extends boolean | undefined>(key: string, {
2023-05-05 01:17:47 +02:00
replace = {},
forceString
2023-05-05 01:17:47 +02:00
}: TranslationParameters<B>): Localized<B> {
let translation = key;
const translations = app.translations[app.locale];
if (translations && translations[key]) {
translation = translations[key];
}
for (let [parameter, replacement] of Object.entries(replace ?? {})) {
// `'attrs' in replacement` checks if `replacement` is a Mithril Vnode.
const isVnode = typeof replacement === 'object' && 'attrs' in replacement;
if (isVnode) {
// Transform vnode to string.
const div = document.createElement('div');
m.render(div, replacement);
replacement = div.innerHTML;
}
translation = translation.replace(`:${parameter}`, replacement as string);
}
2023-05-05 01:17:47 +02:00
return (forceString ? translation : m.trust(translation)) as Localized<B>;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export function __(key: string, replace?: ReplaceObject): string {
return tr(key, {replace, forceString: true});
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export function _v(key: string, replace?: ReplaceObject): Vnode<any, any> {
return tr(key, {replace, forceString: false});
}
/**
* Get the display name of a locale.
*
* @param locale The locale code to get the display name of. If not provided, the current locale will be used.
*/
export function getLocaleDisplayName(locale?: string) {
2023-05-05 01:17:47 +02:00
const lang = locale ?? app.locale;
2023-05-05 01:17:47 +02:00
const intl = new Intl.DisplayNames([lang], {type: 'language'});
return intl.of(lang);
}
export function getFlag(language: string, slot: string = 'start') {
// TODO: Wait https://github.com/material-components/material-web/issues/3933 to be fixed.
return `<img class="flag" src="/vendor/blade-flags/language-${language}.svg" alt="${__('Bandiera della lingua :language', {language: getLocaleDisplayName(language) as string})}" slot="${slot}" style="margin-left: 16px;"/>`;
}