storebound/apps/desktop/src/i18n/index.ts

33 lines
1.3 KiB
TypeScript

// UI strings: English and Turkish catalogs with the same keys (tr.ts is typed against en.ts; tools/i18n-check.ts also
// checks empty strings and placeholder parity in CI). `t(key, vars)`: "{name}" placeholders; with a numeric `count`,
// a "<key>_one" entry is used for 1 when the catalog has one.
import { en } from './en';
import { tr } from './tr';
export type Key = keyof typeof en;
export type Vars = Record<string, string | number>;
export type UiLang = 'en' | 'tr';
export const CATALOGS: Record<UiLang, Record<Key, string>> = { en, tr };
let current: UiLang = 'en';
export function setLang(l: UiLang): void { current = l; }
export function lang(): UiLang { return current; }
export function format(s: string, vars?: Vars): string {
if (!vars) return s;
return s.replace(/\{(\w+)\}/g, (m, k: string) => (vars[k] === undefined ? m : String(vars[k])));
}
export function t(key: Key, vars?: Vars): string {
const cat = CATALOGS[current];
let k: Key = key;
if (vars && vars.count === 1) {
const one = `${key}_one` as Key;
if (one in cat) k = one;
}
return format(cat[k] ?? en[k] ?? key, vars);
}
/** Placeholders of a message ("{count} apps" -> ["count"]), sorted, for the parity check. */
export const placeholders = (s: string): string[] => [...s.matchAll(/\{(\w+)\}/g)].map(m => m[1]!).sort();