8c14913275
Deploy Site / deploy-site (push) Successful in 1m45s
Deploy Client / build-windows (push) Successful in 1m58s
Deploy Client / build-android (push) Successful in 2m10s
Deploy Client / build-macos (push) Successful in 4m2s
Deploy Client / build-ios (push) Successful in 3m40s
Deploy Client / release-deploy (push) Successful in 2m2s
- lib/i18n.ts: Lang/Entry 扩 6 语;STRINGS 130 条补 ja/ko/ru/es;makeT 回退英文
- lib/api/errors.ts: ERROR_TEXT 14 条补 4 语;bilingual 改为 code 本地字典优先
→ 英文字典 → 后端 message → 通用兜底
- lib/theme.tsx: 默认语种 zh→en;localStorage 白名单扩 6 语;setAttribute('lang') 直用 lang
- components/shared.tsx: LangSeg 段控 → 原生 select 6 语下拉
- app/layout.tsx: 默认壳 html lang zh→en;title/desc 改英文
- next build 通过(5 页静态);tsc 干净;无红线词
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
34 lines
5.7 KiB
TypeScript
34 lines
5.7 KiB
TypeScript
// errors.ts — 错误码 → 多语文案映射表(阶段 B 落地)
|
|
import { ApiError } from './types';
|
|
import type { Lang } from '../i18n';
|
|
|
|
/**
|
|
* 后端统一返回 {code, message_zh, message_en};前端优先用本表(按 code 命中当前语言),
|
|
* 再回退后端文案(en 优先),最后 unknown。codes 与 #1 openapi 对齐。
|
|
*/
|
|
export const ERROR_TEXT: Record<string, { zh: string; en: string; ja: string; ko: string; ru: string; es: string }> = {
|
|
invalid_credentials: { zh: '邮箱或密码错误', en: 'Wrong email or password', ja: 'メールアドレスまたはパスワードが違います', ko: '이메일 또는 비밀번호가 올바르지 않습니다', ru: 'Неверная почта или пароль', es: 'Correo o contraseña incorrectos' },
|
|
rate_limited: { zh: '操作过于频繁,请稍后再试', en: 'Too many requests, slow down', ja: 'リクエストが多すぎます。少し時間をおいてください', ko: '요청이 너무 많습니다. 잠시 후 다시 시도하세요', ru: 'Слишком много запросов, помедленнее', es: 'Demasiadas solicitudes, ve más despacio' },
|
|
account_locked: { zh: '失败次数过多,账户已临时锁定', en: 'Too many attempts — account temporarily locked', ja: '試行回数が多すぎます — アカウントを一時的にロックしました', ko: '시도 횟수가 너무 많습니다 — 계정이 일시적으로 잠겼습니다', ru: 'Слишком много попыток — аккаунт временно заблокирован', es: 'Demasiados intentos: la cuenta está bloqueada temporalmente' },
|
|
totp_required: { zh: '需要双重认证动态码', en: 'Two-factor code required', ja: '二要素認証コードが必要です', ko: '2단계 인증 코드가 필요합니다', ru: 'Требуется код двухфакторной аутентификации', es: 'Se requiere el código de verificación en dos pasos' },
|
|
totp_invalid: { zh: '动态码不正确,请重试', en: 'Invalid code, try again', ja: 'コードが正しくありません。もう一度お試しください', ko: '코드가 올바르지 않습니다. 다시 시도하세요', ru: 'Неверный код, попробуйте снова', es: 'Código no válido, inténtalo de nuevo' },
|
|
code_invalid: { zh: '激活码无效', en: 'Invalid activation code', ja: 'アクティベーションコードが無効です', ko: '인증 코드가 유효하지 않습니다', ru: 'Недействительный код активации', es: 'Código de activación no válido' },
|
|
code_used: { zh: '激活码已被使用', en: 'Activation code already used', ja: 'アクティベーションコードは使用済みです', ko: '이미 사용된 인증 코드입니다', ru: 'Код активации уже использован', es: 'El código de activación ya se ha usado' },
|
|
code_expired: { zh: '激活码已过期', en: 'Activation code expired', ja: 'アクティベーションコードの有効期限が切れています', ko: '인증 코드가 만료되었습니다', ru: 'Срок действия кода активации истёк', es: 'El código de activación ha caducado' },
|
|
device_limit: { zh: '设备数量已达上限', en: 'Device limit reached', ja: 'デバイス数が上限に達しました', ko: '기기 수가 한도에 도달했습니다', ru: 'Достигнут лимит устройств', es: 'Se alcanzó el límite de dispositivos' },
|
|
device_not_found: { zh: '设备不存在', en: 'Device not found', ja: 'デバイスが見つかりません', ko: '기기를 찾을 수 없습니다', ru: 'Устройство не найдено', es: 'Dispositivo no encontrado' },
|
|
unauthorized: { zh: '登录已失效,请重新登录', en: 'Session expired, please log in again', ja: 'セッションの有効期限が切れました。再度ログインしてください', ko: '세션이 만료되었습니다. 다시 로그인하세요', ru: 'Сеанс истёк, войдите снова', es: 'La sesión ha caducado, inicia sesión de nuevo' },
|
|
'auth.ticket_invalid': { zh: '登录票据无效或已过期,请重新从 App 打开', en: 'Login ticket is invalid or expired, please reopen from the app', ja: 'ログインチケットが無効か期限切れです。アプリから開き直してください', ko: '로그인 티켓이 유효하지 않거나 만료되었습니다. 앱에서 다시 여세요', ru: 'Токен входа недействителен или истёк, откройте снова из приложения', es: 'El ticket de inicio de sesión no es válido o ha caducado, vuelve a abrirlo desde la app' },
|
|
network: { zh: '网络异常,请稍后重试', en: 'Network error, please retry', ja: 'ネットワークエラーです。後でもう一度お試しください', ko: '네트워크 오류입니다. 잠시 후 다시 시도하세요', ru: 'Ошибка сети, повторите попытку', es: 'Error de red, vuelve a intentarlo' },
|
|
unknown: { zh: '操作失败,请稍后重试', en: 'Something went wrong, please retry', ja: '問題が発生しました。後でもう一度お試しください', ko: '문제가 발생했습니다. 잠시 후 다시 시도하세요', ru: 'Что-то пошло не так, повторите попытку', es: 'Algo salió mal, vuelve a intentarlo' },
|
|
};
|
|
|
|
/** 把任意错误转成当前语言文案(按 code 查表→后端文案 en 优先→通用兜底) */
|
|
export function bilingual(err: unknown, lang: Lang): string {
|
|
if (err instanceof ApiError) {
|
|
const m = ERROR_TEXT[err.code];
|
|
return m?.[lang] ?? m?.en ?? err.message_en ?? err.message_zh ?? ERROR_TEXT.unknown[lang];
|
|
}
|
|
return ERROR_TEXT.unknown[lang];
|
|
}
|