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.
75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
import { createContext, useContext } from 'react';
|
|
import { en, type TranslationKey, type Translations } from './en';
|
|
import { ru } from './ru';
|
|
import type { Locale } from './localeCodes';
|
|
|
|
export type { Locale };
|
|
|
|
const bundles: Record<Locale, Translations> = { en, ru };
|
|
|
|
/** Detect locale from Telegram WebApp or browser */
|
|
export function detectLocale(): Locale {
|
|
// Check localStorage first (user override)
|
|
try {
|
|
const saved = localStorage.getItem('autohero_locale');
|
|
if (saved === 'en' || saved === 'ru') return saved;
|
|
} catch { /* ignore */ }
|
|
|
|
// Telegram Mini App language
|
|
try {
|
|
const tg = (window as any).Telegram?.WebApp;
|
|
const lang: string | undefined =
|
|
tg?.initDataUnsafe?.user?.language_code ?? tg?.language_code;
|
|
if (lang?.startsWith('ru')) return 'ru';
|
|
} catch { /* ignore */ }
|
|
|
|
// Browser language fallback
|
|
const nav = navigator.language ?? (navigator as any).userLanguage ?? '';
|
|
if (nav.startsWith('ru')) return 'ru';
|
|
|
|
return 'en';
|
|
}
|
|
|
|
// ---- Context ----
|
|
|
|
interface I18nValue {
|
|
tr: Translations;
|
|
locale: Locale;
|
|
setLocale: (l: Locale) => void;
|
|
}
|
|
|
|
export const I18nContext = createContext<I18nValue>({
|
|
tr: en,
|
|
locale: 'en',
|
|
setLocale: () => {},
|
|
});
|
|
|
|
/** Hook: returns the full translation object for the current locale */
|
|
export function useT(): Translations {
|
|
return useContext(I18nContext).tr;
|
|
}
|
|
|
|
/** Hook: returns locale + setter for the settings UI */
|
|
export function useLocale(): { locale: Locale; setLocale: (l: Locale) => void } {
|
|
const { locale, setLocale } = useContext(I18nContext);
|
|
return { locale, setLocale };
|
|
}
|
|
|
|
/**
|
|
* Interpolate {placeholders} in a translation string.
|
|
* Usage: t(translations.levelUp, { level: 5 }) => "Level up! Now level 5"
|
|
*/
|
|
export function t(template: string, vars?: Record<string, string | number>): string {
|
|
if (!vars) return template;
|
|
return template.replace(/\{(\w+)\}/g, (_, key) =>
|
|
vars[key] != null ? String(vars[key]) : `{${key}}`,
|
|
);
|
|
}
|
|
|
|
/** Get translations bundle for a locale */
|
|
export function getTranslations(locale: Locale): Translations {
|
|
return bundles[locale] ?? en;
|
|
}
|
|
|
|
export type { TranslationKey, Translations };
|