Apps, web, i18n, UI, partners, payouts, backoffice, bariki, prod infra
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
45d7512d2b
commit
3489e0b816
319 files changed
+45483
-121
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';
|
||||
import { createT, formatAmd, formatDateTime, isLocale, type Locale, type TFunction } from '@barev/i18n';
|
||||
import { reportClientError } from './telegram.ts';
|
||||
|
||||
interface I18nValue {
|
||||
locale: Locale;
|
||||
t: TFunction;
|
||||
setLocale: (l: Locale) => void;
|
||||
amd: (n: number) => string;
|
||||
dt: (d: Date, opts?: Intl.DateTimeFormatOptions) => string;
|
||||
}
|
||||
|
||||
const Ctx = createContext<I18nValue | null>(null);
|
||||
|
||||
export function pickLocale(...candidates: (string | null | undefined)[]): Locale {
|
||||
for (const c of candidates) {
|
||||
const base = c?.split('-')[0]?.toLowerCase();
|
||||
if (isLocale(base)) return base;
|
||||
}
|
||||
return 'ru';
|
||||
}
|
||||
|
||||
export function I18nProvider({ initial, children }: { initial: Locale; children: ReactNode }) {
|
||||
const [locale, setLocale] = useState<Locale>(initial);
|
||||
useEffect(() => setLocale(initial), [initial]);
|
||||
useEffect(() => {
|
||||
document.documentElement.lang = locale;
|
||||
}, [locale]);
|
||||
const value = useMemo<I18nValue>(
|
||||
() => ({
|
||||
locale,
|
||||
t: createT(locale),
|
||||
setLocale,
|
||||
amd: (n) => formatAmd(locale, n),
|
||||
dt: (d, opts) => formatDateTime(locale, d, opts),
|
||||
}),
|
||||
[locale],
|
||||
);
|
||||
return <Ctx.Provider value={value}>{children}</Ctx.Provider>;
|
||||
}
|
||||
|
||||
export function useI18n(): I18nValue {
|
||||
const v = useContext(Ctx);
|
||||
if (!v) throw new Error('I18nProvider missing');
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Текст ошибки API: errors.<код бизнес-ошибки> или общий */
|
||||
export function errorText(t: TFunction, err: unknown): string {
|
||||
reportClientError(err, 'errorText');
|
||||
const e = err as { data?: { domainCode?: string | null; code?: string }; message?: string } | null;
|
||||
const code = e?.data?.domainCode ?? e?.message;
|
||||
if (code && /^[A-Z0-9_]+$/.test(code)) {
|
||||
const s = t(`errors.${code}`);
|
||||
if (s !== `errors.${code}`) return s;
|
||||
}
|
||||
return t('errors.generic');
|
||||
}
|
||||
Reference in new issue
Block a user