with one click
i18n
给 web/ 前端组件接入多语言(中英)。当用户说加多语言、国际化、i18n、翻译、某页面没翻译、硬编码中文时触发。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
给 web/ 前端组件接入多语言(中英)。当用户说加多语言、国际化、i18n、翻译、某页面没翻译、硬编码中文时触发。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
恢复上下文。在 /clear 后或新 session 开始时使用。当用户说恢复上下文、继续之前的工作、catchup 时触发。
审查当前 git diff 中的 Go 代码。当用户说审查 Go 代码、review Go、检查代码时触发。
运行 Go 测试并分析结果。当用户说跑测试、运行测试、go test 时触发。
在已有 go-zero 服务里新增一个 HTTP 接口。当用户说加接口、新增 api、加路由时触发。
新增数据库模型/表。当用户说加表、新增 model、加数据库字段时触发。
在已有 go-zero 服务里新增一个 RPC 方法。当用户说加 rpc 方法、新增 grpc、新加 proto 接口时触发。
| name | i18n |
| description | 给 web/ 前端组件接入多语言(中英)。当用户说加多语言、国际化、i18n、翻译、某页面没翻译、硬编码中文时触发。 |
给 web/ 前端的用户可见文本接入多语言。本项目不用 react-i18next,也没有 web/src/i18n/locales/*.json(CLAUDE.md / frontend.md 里那句已过时,以本文为准)。
web/src/lib/i18n.ts —— 一个扁平对象 dict['zh-CN'] / dict['en'],key 用点号命名(如 trend.publish)。t(key, lang),缺失时回退 zh-CN,再回退 key 本身。不支持占位符插值。web/src/hooks/use-i18n.ts 的 useT(),返回 (key) => translate(key, lang),lang 来自 useSettingsStore(s => s.language)。.replace(),例如 t('trend.imageLimit').replace('{count}', String(n))。cd web
# 列某组件里所有非注释的中文行
grep -nE "[一-鿿]" src/components/im/Xxx.tsx | grep -vE "^\s*[0-9]+:\s*(//|/\*|\*)"
逐条判断是否用户可见(按钮/标题/placeholder/title/toast/空态/确认弹窗都算)。不该翻译的:语言名本身(简体中文 / English)、代码注释、日志、接口字段名。
lib/i18n.ts 加 key在 zh-CN 块末尾和 en 块末尾各加一组,分组写注释,两边 key 必须一一对应:
// zh-CN 块
'xxx.title': '我的相册',
'xxx.itemCount': '{count} 项',
// en 块
'xxx.title': 'Album',
'xxx.itemCount': '{count} items',
trend.* / fav.* / pe.* / sec.* / upc.* 等)。common.save/cancel/confirm/back/loadMore、时间 group.time.justNow/minutesAgo/hoursAgo/monthDay、在线 chat.online/offline。useTimport { useT } from '@/hooks/use-i18n';
export default function Xxx() {
const t = useT(); // 必须在所有 early return 之前(Hooks 规则)
...
<span>{t('xxx.title')}</span>
<input placeholder={t('xxx.search')} />
toast.success(t('xxx.saved'));
<div>{t('xxx.itemCount').replace('{count}', String(n))}</div>
}
每个子组件都要各自 const t = useT() —— 子组件拿不到父组件的 t。
cd web && npx tsc --noEmit -p tsconfig.json 2>&1 | grep <你改的文件名>
# 再确认无残留(排除注释/语言名/兜底)
grep -nE "[一-鿿]" src/components/im/Xxx.tsx | grep -vE "//|/\*|\*|简体中文"
预存的既有报错(如 aspectSquare/ringColor)与本次无关,只看自己文件。
const TYPE_MAP = {1:{label:'文本'}}):函数体外拿不到 t。把 label:'文本' 改成 labelKey:'trend.type.text',渲染时 t(cfg.labelKey)。fmtTime / getUserName):加一个 t 参数 fmtTime(date, t),所有调用点传进去。.map(t => ...)、const t = list.find(...) 会把翻译函数 t 遮蔽。重命名迭代/局部变量(tr / ty),别动翻译函数名。useT() 不能放在 if (!open) return null 之后。你的数据将<strong>永久删除</strong> 这种,拆成 t('a')<strong>{t('b')}</strong>t('c') 三段 key。perl -0pi -e "s/.../.../g"(不要加 -CSD,否则中文字节与解码不匹配会全部 miss)。t() 包裹,不许硬编码中文。zh-CN 与 en 两边 key 必须对齐,缺一边会回退中文。frontend.md)。feat: / fix:),英文,无署名。