34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
// Tiny i18n harness — Russian primary, English fallback (BCP-47 prefix
|
|
// match — any `en` variant). Bootstrap forwards `clientLanguage` from the
|
|
// host; main.tsx can also call `createT()` without args before bootstrap
|
|
// completes (falls back to navigator.language, then RU).
|
|
//
|
|
// Identical mechanics to apps/widget-telegram/src/i18n/index.ts; the
|
|
// Discord widget keeps its own dictionary file because the copy differs —
|
|
// QR-only flow, no SMS, no 2FA password form.
|
|
|
|
import { RU, type StringKey } from './ru';
|
|
import { EN } from './en';
|
|
|
|
const interpolate = (s: string, vars?: Record<string, string>): string => {
|
|
if (!vars) return s;
|
|
return s.replace(/\{(\w+)\}/g, (_, k) => vars[k] ?? `{${k}}`);
|
|
};
|
|
|
|
const pickDict = (clientLanguage: string | undefined): Record<StringKey, string> => {
|
|
const lang = (
|
|
clientLanguage ||
|
|
(typeof navigator !== 'undefined' ? navigator.language : '') ||
|
|
'ru'
|
|
).toLowerCase();
|
|
return lang.startsWith('en') ? EN : RU;
|
|
};
|
|
|
|
export type T = (key: StringKey, vars?: Record<string, string>) => string;
|
|
|
|
export const createT = (clientLanguage?: string): T => {
|
|
const dict = pickDict(clientLanguage);
|
|
return (key, vars) => interpolate(dict[key], vars);
|
|
};
|
|
|
|
export type { StringKey };
|