import { DEFAULT_LOCALE, type Locale } from '@/i18n/config'; /** * 单文件翻译字典。 * * 设计(按你的要求): * - key 就是「英文原文」,直接当文案用,无需额外维护英文副本; * - value 只存「非默认语言」的翻译(本项目默认语言是 en,所以只存 cn 等); * - 英文环境调用 t(key) 直接返回 key 本身; * - 其它语言从 value 里取对应翻译,取不到就回退英文(开发环境会告警,方便发现漏翻)。 * * 新增一条:直接加一行 `'英文原文': { cn: '中文' }` 即可; * 当前是英文时根本不需要在字典里登记,写了 t('Nice day!') 就能渲染 "Nice day!"。 */ // 除默认语言外的所有语言(如 'cn')。加新语言(ja 等)时这里会自动包含。 type OtherLocale = Exclude; type TranslationEntry = Partial>; export const dict: Record = { // ── 导航 / Navigation ── 'about': { cn: '关于' }, '全部的 runway': { cn: '全部的 runway' }, 'contact': { cn: '联系' }, 'contact us': { cn: '联系我们' }, 'home': { cn: '首页' }, 'latest projects': { cn: '最新项目' }, 'login': { cn: '登录' }, 'portfolio': { cn: '作品集' }, 'runway archive': { cn: '走秀档案' }, 'signup': { cn: '注册' }, // ── 控件 / Controls ── 'back to index': { cn: '返回首页' }, 'back to top': { cn: '回到顶部' }, 'close': { cn: '关闭' }, 'previous image': { cn: '上一张' }, 'next image': { cn: '下一张' }, 'previous': { cn: '上一组' }, 'next': { cn: '下一组' }, // ── 错误 / Errors ── 'no article id specified': { cn: '未指定文章 ID' }, 'failed to load article. please refresh or try later.': { cn: '加载文章失败,请刷新或稍后再试' }, 'click image to zoom · scroll to view · esc to close': { cn: '点击图片放大 · 上下滚动查看 · Esc 关闭' }, // ── 页脚 / Footer ── '© 2026 portfolio studio. all rights reserved.': { cn: '© 2026 PORTFOLIO STUDIO. 保留所有权利。' }, // ── 页脚工具 / Footer tools ── 'color studio tools': { cn: '色彩工作室工具' }, 'ai color trend generator': { cn: 'AI 色彩趋势生成器' }, 'photo swatch extractor': { cn: '图片色板提取器' }, 'upload': { cn: '上传' }, 'reset b&w theme': { cn: '重置黑白主题' }, 'default': { cn: '默认' }, // ── 页脚简介 / Manifesto ── 'minimalist editorial portfolio documenting haute couture shows, backstage fittings, and street culture. integrated with 2026 color forecast intelligence and ai palette generator.': { cn: '极简编辑风格作品集,记录高级定制秀场、后台试装与街头文化。集成 2026 色彩预测情报与 AI 调色板生成器。' }, // ── 登录态 / Auth ── 'hi': { cn: '你好' }, 'logout': { cn: '退出' }, 'language': { cn: '语言' }, 'runway looks': { cn: '秀场造型' }, // ── 街拍 / Street Snaps ── 'street style': { cn: '街拍' }, 'street snaps': { cn: '街拍' }, 'all street snaps': { cn: '全部街拍' }, 'no street snap id specified': { cn: '未指定街拍 ID' }, 'failed to load street snap. please refresh or try later.': { cn: '加载街拍失败,请刷新或稍后再试' } }; /** 把 {name} 形式的占位符替换成参数值。 */ function interpolate(text: string, params?: Record): string { if (!params) return text; return text.replace(/\{(\w+)\}/g, (_, k) => (k in params ? String(params[k]) : `{${k}}`)); } /** * 取翻译: * - 当前是默认语言(en)→ 直接返回 key(英文原文); * - 其它语言 → 优先取字典里的翻译,缺失则回退英文并返回 key(不会白屏)。 */ export function translate(key: string, locale: Locale, params?: Record): string { if (locale === DEFAULT_LOCALE) return interpolate(key, params); const localized = dict[key.toLowerCase()]?.[locale as OtherLocale]; if (localized) return interpolate(localized, params); if (import.meta.env.DEV) { console.warn(`[i18n] 缺少 "${locale}" 翻译:"${key}",已回退英文`); } return interpolate(key, params); }