| |
| |
| |
| |
| |
| |
|
|
| interface ApiErrorLike { |
| status?: number |
| code?: number | string |
| message?: string |
| error?: string |
| reason?: string |
| metadata?: Record<string, unknown> |
| response?: { |
| data?: { |
| detail?: string |
| message?: string |
| code?: number | string |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function extractApiErrorCode(err: unknown): string | undefined { |
| if (!err || typeof err !== 'object') return undefined |
| const e = err as ApiErrorLike |
| const code = e.reason ?? e.code ?? e.response?.data?.code |
| return code != null ? String(code) : undefined |
| } |
|
|
| |
| |
| |
| |
| export function extractApiErrorMetadata(err: unknown): Record<string, unknown> | undefined { |
| if (!err || typeof err !== 'object') return undefined |
| const e = err as ApiErrorLike |
| return e.metadata |
| } |
|
|
| type TranslateFn = (key: string, params?: Record<string, unknown>) => string |
| type TranslateWithExistsFn = TranslateFn & { te?: (key: string) => boolean } |
|
|
| |
| |
| |
| |
| function tryTranslate(t: TranslateFn, key: string, fallback: string): string { |
| const translated = t(key) |
| if (translated === key) return fallback |
| const te = (t as TranslateWithExistsFn).te |
| if (te && !te(key)) return fallback |
| return translated |
| } |
|
|
| |
| |
| |
| |
| |
| function localizeMetadata(metadata: Record<string, unknown>, t: TranslateFn): Record<string, unknown> { |
| const out: Record<string, unknown> = { ...metadata } |
| if (typeof out.key === 'string') { |
| out.key = tryTranslate(t, `admin.settings.payment.field_${out.key}`, out.key) |
| } |
| if (typeof out.keys === 'string') { |
| out.keys = out.keys |
| .split('/') |
| .map(k => tryTranslate(t, `admin.settings.payment.field_${k}`, k)) |
| .join(' / ') |
| } |
| return out |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export function extractI18nErrorMessage( |
| err: unknown, |
| t: TranslateFn, |
| namespace: string, |
| fallback: string, |
| ): string { |
| const code = extractApiErrorCode(err) |
| if (code) { |
| const key = `${namespace}.${code}` |
| const rawMetadata = extractApiErrorMetadata(err) ?? {} |
| const metadata = localizeMetadata(rawMetadata, t) |
| const translated = t(key, metadata) |
| |
| if (translated !== key) return translated |
| |
| const te = (t as TranslateWithExistsFn).te |
| if (te && te(key)) return translated |
| } |
| return extractApiErrorMessage(err, fallback) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function extractApiErrorMessage( |
| err: unknown, |
| fallback = 'Unknown error', |
| i18nMap?: Record<string, string>, |
| ): string { |
| if (!err) return fallback |
|
|
| |
| if (i18nMap) { |
| const code = extractApiErrorCode(err) |
| if (code && i18nMap[code]) return i18nMap[code] |
| } |
|
|
| |
| if (typeof err === 'object' && err !== null) { |
| const e = err as ApiErrorLike |
| |
| if (e.message) return e.message |
| if (e.error) return e.error |
| |
| if (e.response?.data?.detail) return e.response.data.detail |
| if (e.response?.data?.message) return e.response.data.message |
| } |
|
|
| |
| if (err instanceof Error) return err.message |
|
|
| |
| const str = String(err) |
| return str === '[object Object]' ? fallback : str |
| } |
|
|