import { texts } from '@/texts' const PERSIAN_TEXT_PATTERN = /[\u0600-\u06ff]/ const ERROR_CODE_MESSAGES: Record = { ...texts.errors.codes } const STATUS_MESSAGES: Record = Object.fromEntries( Object.entries(texts.errors.httpStatus).map(([status, message]) => [Number(status), message]) ) const DEFAULT_API_ERROR_MESSAGE = texts.errors.defaultApi export const containsPersianText = (value: string): boolean => PERSIAN_TEXT_PATTERN.test(value) export const getProductApiErrorMessage = (code: string): string | undefined => ERROR_CODE_MESSAGES[code.toUpperCase()] /** * API error codes stay machine-readable, while every user-facing message is * guaranteed to contain Persian texts. Unknown English server details are not * exposed because they are often framework or database implementation text. */ export const ensurePersianApiErrorMessage = (message: unknown, status?: number, code?: string): string => { if (typeof message === 'string') { const trimmed = message.trim() if (trimmed && containsPersianText(trimmed)) return trimmed } if (code) { const localizedCodeMessage = ERROR_CODE_MESSAGES[code.toUpperCase()] if (localizedCodeMessage) return localizedCodeMessage } if (status) { return STATUS_MESSAGES[status] ?? (status >= 500 ? STATUS_MESSAGES[500] : DEFAULT_API_ERROR_MESSAGE) } return DEFAULT_API_ERROR_MESSAGE } const localizeMessageValue = (message: unknown, status?: number, code?: string): string | string[] => { if (!Array.isArray(message)) return ensurePersianApiErrorMessage(message, status, code) const localized = message.map((item) => ensurePersianApiErrorMessage(item, status, code)) return [...new Set(localized)] } /** Returns an error payload with Persian top-level and nested body messages. */ export const localizeApiErrorPayload = (data: unknown, status?: number): Record => { const source = data && typeof data === 'object' && !Array.isArray(data) ? (data as Record) : {} const code = typeof source.code === 'string' ? source.code : undefined const body = source.body && typeof source.body === 'object' && !Array.isArray(source.body) ? (source.body as Record) : undefined const bodyCode = typeof body?.code === 'string' ? body.code : code const localized: Record = { ...source, success: false, message: localizeMessageValue(source.message ?? data, status, code), } if (body) { localized.body = { ...body, message: localizeMessageValue(body.message, status, bodyCode), } } return localized }