diff --git a/site/build.mjs b/site/build.mjs index fdc6b65..7d9fbcf 100644 --- a/site/build.mjs +++ b/site/build.mjs @@ -274,6 +274,90 @@ const T = { { q: 'How do I update or uninstall?', a: 'Update: re-run npx superpowers-zh to overwrite. Uninstall: npx superpowers-zh --uninstall for the current project; npx superpowers-zh --global --uninstall for a global install.' }, ], }, + zht: { + htmlLang: 'zh-Hant', + title: 'superpowers-zh · AI 編程超能力中文增強版', + desc: 'superpowers(250k+ ⭐)完整漢化 + 4 個中國原創 skills,一條 npx 命令為 20 款 AI 編程工具裝上系統化工作方法論。', + nav: { why: '特性', install: '安裝', skills: 'Skills', tools: '支援工具', faq: 'FAQ', learn: '學習 ↗', github: 'GitHub ↗' }, + heroBadge: 'superpowers 250k+ ⭐ · 完整漢化 + 中國原創', + heroH1: '給你的 AI 編程工具
裝上真正會幹活的超能力', + heroLead: '{n} 個經過實戰驗證的工作方法論 skill —— 從頭腦風暴到 TDD,從系統化除錯到程式碼審查。
一條命令,自動識別專案裡的工具並安裝。', + heroBtn1: '查看安裝命令', heroBtn2: 'GitHub 原始碼', + stats: ['Skills', '中國原創', '支援工具', '目前版本'], + whyTitle: '為什麼選擇 superpowers-zh?', + whySub: '不是又一套提示詞範本 —— 是讓 AI 真正按工程方法幹活的系統化能力。', + plTitle: '一條龍工作流,每一步都有 skill 把關', + plSub: 'skill 之間彼此銜接,AI 會在合適的節點自動觸發對應方法論。', + cmpTitle: '裝上之後,AI 不再「上來就寫」', + cmpBad: '❌ 沒裝', cmpGood: '✅ 裝了 superpowers-zh', + cmpBadPre: '你:給使用者模組加個批次匯出功能\nAI:好的,我來實作……(直接開寫)\n export async function exportUsers() { … }\n你:等等,格式不對,沒分頁,\n 大量資料會 OOM……', + cmpGoodPre: '你:給使用者模組加個批次匯出功能\nAI:先理清需求 —— 匯出格式?資料量級?\n 要分頁/串流嗎?要權限校驗嗎?\n (觸發 brainstorming)\n → 寫計畫 → TDD → 驗證 → 審查', + instTitle: '選你的工具,拿到安裝命令', + instSub: '大多數工具 npx superpowers-zh 會自動識別專案目錄並安裝;識別不出的用 --tool 指定。', + instLabel: '我用的是', + instNoteAuto: '在你的專案根目錄執行,自動識別 {name} 並安裝。安裝後重啟工具即可生效。', + instNoteManual: '{name} 無法自動識別,需用 --tool 顯式指定。在專案根目錄執行,安裝後重啟工具即可生效。', + skTitle: '{n} 個 Skill,覆蓋開發全流程', + skSub: '點擊任意卡片查看完整操作文件。', + skSearch: '搜尋 skill…(如 除錯 / review / TDD)', + skEmpty: '沒有符合的 skill。', + skDetail: '查看文件 →', + tagCn: '中國原創', + ucTitle: '典型使用場景', ucSub: '每個場景背後都是一組協同工作的 skill。', + toolsTitle: '一套 skill,20 款工具通用', toolsSub: '換工具不用換習慣,方法論跟著你走。', + faqTitle: '常見問題', + bookTitle: '裝好之後,配上方法論效率翻倍', + bookDesc: '《AI 編程實戰 · 方法論三卷書》—— 10 個 AI 編程工具完整教程 + 真實踩坑。線上書 + PDF,永久免費。', + bookBtn: '免費閱讀 ↗', + aiolaolaBtn: '免費學 AI 編程 · aiOlaOla ↗', + ctaTitle: '準備好讓 AI 真正會幹活了嗎?', + ctaDesc: '一條命令,{n} 個實戰方法論裝進你的工具。免費、開源、零依賴。', + ctaBtn1: '查看安裝命令', ctaBtn2: '⭐ Star on GitHub', + footCols: [ + { h: '產品', links: [['特性', '#why'], ['Skills', '#skills'], ['支援工具', '#tools'], ['FAQ', '#faq']] }, + { h: '資源', links: [['GitHub', 'https://github.com/jnMetaCode/superpowers-zh'], ['npm', 'https://www.npmjs.com/package/superpowers-zh'], ['方法論三卷書', 'https://book.aibuzhiyu.com/']] }, + { h: '生態', links: [['aiOlaOla · 從零學會 AI 編程', 'https://aiolaola.com/?utm_source=sp1'], ['X / Twitter', 'https://x.com/jnMetaCode'], ['公眾號 AI不止語', 'https://aiolaola.com/'], ['姊妹專案', 'https://github.com/jnMetaCode']] }, + { h: '社群', links: [['提交 Issue', 'https://github.com/jnMetaCode/superpowers-zh/issues'], ['貢獻指南', 'https://github.com/jnMetaCode/superpowers-zh/blob/main/CLAUDE.md'], ['聯絡信箱', 'mailto:jnMetaCode@qq.com']] }, + ], + footTag: 'AI 編程超能力 · 中文增強版 · MIT License', + copyright: '© 2026 superpowers-zh · MIT License', + followUs: '掃碼關注', qrWechat: '公眾號 · AI不止語', qrDouyin: '抖音 · @AI不止語(AIBZY)', + copy: '複製', copied: '已複製 ✓', + backToSkills: '← 返回全部 Skill', + detailInstall: '安裝此 skill', + detailSource: '在 GitHub 查看原始檔 ↗', + features: [ + { icon: '🧠', t: '20 個實戰方法論', d: '不是 prompt 範本,是經過跨會話對抗式壓力測試調優的工作方法論 —— 從頭腦風暴到 TDD、除錯、程式碼審查。' }, + { icon: '🔌', t: '20 款工具通用', d: '一套 skill,Claude Code / Cursor / Codex / Gemini CLI / Windsurf… 全適配,換工具不用換習慣。' }, + { icon: '⚡', t: '一條命令安裝', d: 'npx superpowers-zh 自動識別專案裡用的是哪款工具並安裝,零設定,裝完重啟即生效。' }, + { icon: '🇨🇳', t: '中國原創 Skills', d: '中文程式碼審查話術、中文提交規範、中文文件排版、國內 Git 平台(Gitee/Coding/極狐)設定 —— 上游沒有。' }, + { icon: '📖', t: '完整漢化上游', d: '同步 obra/superpowers(250k+ ⭐),核心 skill 全部中文母語化,不是機翻,是逐條校準。' }, + { icon: '🔓', t: '零依賴 · MIT 開源', d: '純 Markdown skill,不引入任何外部依賴、不連網、不上傳程式碼,按需觸發零執行時開銷。' }, + ], + pipeline: [ + { n: '頭腦風暴', d: '動手前先理清意圖與需求' }, + { n: '寫計畫', d: '把需求拆成可執行步驟' }, + { n: 'TDD', d: '先寫測試再寫實作' }, + { n: '系統化除錯', d: '先重現定位再改' }, + { n: '程式碼審查', d: '合併前嚴謹驗收' }, + { n: '完成前驗證', d: '用證據證明真的好了' }, + ], + usecases: [ + { tag: '開發新功能', skills: 'brainstorming → writing-plans → TDD', desc: 'AI 先反問需求、寫出實作計畫,再用測試驅動落地,而不是上來就糊一坨程式碼。' }, + { tag: '修 Bug', skills: 'systematic-debugging', desc: '強制先重現、定位根因,再提修復方案 —— 杜絕「猜一個改一下」的瞎試迴圈。' }, + { tag: '提交 / 合併前', skills: 'verification-before-completion → code-review', desc: '必須跑驗證命令、拿證據說話,再走一輪程式碼審查,才允許聲稱「完成」。' }, + { tag: '國內團隊協作', skills: 'chinese-commit-conventions → chinese-code-review', desc: '中文 commit 規範 + 分級 review 話術,配 Gitee / Coding / 極狐 GitLab 工作流。' }, + ], + faq: [ + { q: 'superpowers-zh 是免費的嗎?', a: '完全免費。MIT 協議開源,永久免費,不含任何付費牆或訂閱。' }, + { q: '支援哪些 AI 編程工具?', a: '共 20 款:Claude Code、Cursor、Windsurf、Codex CLI、Gemini CLI、Kiro、Trae、Qoder、CodeBuddy(騰訊)、CodeArts(華為雲碼道)、Aider、OpenCode、Qwen Code、Antigravity、DeerFlow、VS Code(Copilot)、Copilot CLI、Hermes Agent、Claw Code、OpenClaw。' }, + { q: 'superpowers-zh 有哪些獨特價值?', a: '一套完整中文化的系統工作方法論:從頭腦風暴、規劃、TDD 到除錯、程式碼審查,每個 skill 都是實戰驗證的工作流;並疊加 4 個面向中國開發者的原創 skill(中文程式碼審查 / Git 工作流 / 文件規範 / 提交規範),適配 20 款 AI 編程工具。MIT 協議開源,永久免費。' }, + { q: '安裝後怎麼生效?', a: 'npx 會把 skill 檔案裝到你專案對應工具的目錄(如 .claude/skills/),重啟 AI 工具後,它會在恰當時機自動觸發相應 skill —— 無需你每次手動呼叫。' }, + { q: '能一次裝好、所有專案都用嗎?(全域安裝)', a: '能。npx superpowers-zh --global 裝到工具的使用者級目錄(如 ~/.claude/skills),所有專案自動共享,更新時只需重裝一次。專案級優先、全域兜底,二者可共存。支援全域的工具(均為各工具文件確認的載入路徑):Claude Code / Codex CLI / Qoder / Windsurf / Qwen Code / OpenClaw / OpenCode;其餘工具(含 Gemini / Antigravity,有各自專屬全域方式)請在專案內安裝或參考對應文件。' }, + { q: '會拖慢我的 AI 嗎?會上傳程式碼嗎?', a: '不會。skill 是按需觸發的純 Markdown,零執行時、不連網、不上傳任何程式碼或資料,全程在本機。' }, + { q: '怎麼更新或解除安裝?', a: '更新:重新執行 npx superpowers-zh 覆蓋即可。解除安裝:npx superpowers-zh --uninstall 清理目前專案;全域安裝用 npx superpowers-zh --global --uninstall 清理。' }, + ], + }, }; // ---- 读取 skills(含正文) ---- @@ -305,11 +389,30 @@ function loadSkills() { return skills; } +// ---- 多语言配置:新增语言只需往这里加一项 + 写一个 T. 翻译对象 ---- +// dir: 该语言站点子目录(根语言为 '');hreflang: SEO 语言标记;label: 语言切换器显示名 +const LANGS = [ + { code: 'zh', dir: '', label: '中文', hreflang: 'zh-CN' }, + { code: 'en', dir: 'en/', label: 'EN', hreflang: 'en' }, + { code: 'zht', dir: 'zh-Hant/', label: '繁體', hreflang: 'zh-Hant' }, +]; +const DEFAULT_DIR = LANGS[0].dir; // 根语言(zh)用于 x-default + // ---- 公共布局 ---- -// base: 资源相对前缀('' / '../' / '../../');langHref: 切换语言的目标 URL -function layout({ lang, base, title, desc, body, langHref, canonical = '/', altZh = '/', altEn = '/en/', extraHead = '' }) { +// pageClean: 语言无关的 canonical 后缀(首页 '';skill 页 'skills/') +// pageFile: 语言无关的文件后缀,用于语言切换链接(首页 '';skill 页 'skills/.html') +// base: 资源相对前缀('' / '../' / '../../'),仅用于品牌链接等相对引用 +function layout({ lang, base, title, desc, body, pageClean = '', pageFile = '', extraHead = '' }) { const t = T[lang]; - const other = lang === 'zh' ? 'EN' : '中文'; + const curDir = LANGS.find(l => l.code === lang).dir; + const canonical = `/${curDir}${pageClean}`; + const altLinks = LANGS + .map(l => ``) + .join('\n') + `\n`; + const langSwitch = LANGS + .filter(l => l.code !== lang) + .map(l => `${l.label}`) + .join(''); return ` @@ -322,9 +425,7 @@ function layout({ lang, base, title, desc, body, langHref, canonical = '/', altZ ${esc(title)} - - - +${altLinks} @@ -351,7 +452,7 @@ ${extraHead} ${t.nav.faq} ${t.nav.learn} ${t.nav.github} - ${other} + ${langSwitch} @@ -387,8 +488,8 @@ function renderLanding(skills, lang) { const fill = (s, map) => s.replace(/\{(\w+)\}/g, (_, k) => map[k]); const cards = skills.map(s => { - const title = lang === 'zh' ? s.title : s.titleEn; - const d = lang === 'zh' ? s.desc : (s.descEn || s.desc); + const title = lang === 'en' ? s.titleEn : s.title; + const d = lang === 'en' ? (s.descEn || s.desc) : s.desc; return `

${esc(title)}

${s.china ? `${t.tagCn}` : ''}
@@ -506,7 +607,7 @@ function renderLanding(skills, lang) { // ---- skill 详情(操作文档)页正文 ---- function renderDetail(skill, lang) { const t = T[lang]; - const title = lang === 'zh' ? skill.title : skill.titleEn; + const title = lang === 'en' ? skill.titleEn : skill.title; const bodyHtml = renderMarkdown(skill.raw); const cnNotice = lang === 'en' ? '
📖 This skill\'s content is written in Chinese — superpowers-zh is a Chinese-localized toolkit.
' @@ -550,31 +651,28 @@ function build() { copyFileSync(join(TEMPLATE, 'assets', 'qr-wechat.jpg'), join(DIST, 'assets', 'qr-wechat.jpg')); copyFileSync(join(TEMPLATE, 'assets', 'qr-douyin.jpg'), join(DIST, 'assets', 'qr-douyin.jpg')); - // 中文站(根) - writeFileSync(join(DIST, 'index.html'), layout({ - lang: 'zh', base: '', title: T.zh.title, desc: T.zh.desc, - body: renderLanding(skills, 'zh'), langHref: 'en/index.html', - canonical: '/', altZh: '/', altEn: '/en/', - })); - // 英文站(/en/) - writeFileSync(join(DIST, 'en', 'index.html'), layout({ - lang: 'en', base: '../', title: T.en.title, desc: T.en.desc, - body: renderLanding(skills, 'en'), langHref: '../index.html', - canonical: '/en/', altZh: '/', altEn: '/en/', - })); - - // 详情(操作文档)页 ×2 语言 - for (const s of skills) { - writeFileSync(join(DIST, 'skills', `${s.name}.html`), layout({ - lang: 'zh', base: '../', title: `${s.title} · superpowers-zh`, desc: s.desc, - body: renderDetail(s, 'zh'), langHref: `../en/skills/${s.name}.html`, - canonical: `/skills/${s.name}`, altZh: `/skills/${s.name}`, altEn: `/en/skills/${s.name}`, - })); - writeFileSync(join(DIST, 'en', 'skills', `${s.name}.html`), layout({ - lang: 'en', base: '../../', title: `${s.titleEn} · superpowers-zh`, desc: s.descEn || s.desc, - body: renderDetail(s, 'en'), langHref: `../../skills/${s.name}.html`, - canonical: `/en/skills/${s.name}`, altZh: `/skills/${s.name}`, altEn: `/en/skills/${s.name}`, + // ---- 每种语言生成首页 + 全部 skill 详情页 ---- + for (const L of LANGS) { + const t = T[L.code]; + const dirParts = L.dir ? [L.dir.replace(/\/$/, '')] : []; + const homeBase = L.dir ? '../' : ''; + mkdirSync(join(DIST, ...dirParts, 'skills'), { recursive: true }); + // 首页 + writeFileSync(join(DIST, ...dirParts, 'index.html'), layout({ + lang: L.code, base: homeBase, title: t.title, desc: t.desc, + body: renderLanding(skills, L.code), pageClean: '', pageFile: '', })); + // skill 详情页 + for (const s of skills) { + const title = L.code === 'en' ? s.titleEn : s.title; + const desc = L.code === 'en' ? (s.descEn || s.desc) : s.desc; + writeFileSync(join(DIST, ...dirParts, 'skills', `${s.name}.html`), layout({ + lang: L.code, base: L.dir ? '../../' : '../', + title: `${title} · superpowers-zh`, desc, + body: renderDetail(s, L.code), + pageClean: `skills/${s.name}`, pageFile: `skills/${s.name}.html`, + })); + } } // ---- SEO: robots.txt + sitemap.xml ---- @@ -582,11 +680,14 @@ function build() { 'User-agent: *\nAllow: /\n\nSitemap: ' + SITE_URL + '/sitemap.xml\n'); const today = new Date().toISOString().slice(0, 10); - const urls = ['/', '/en/']; - for (const s of skills) { urls.push(`/skills/${s.name}`, `/en/skills/${s.name}`); } + const urls = []; + for (const L of LANGS) { + urls.push(`/${L.dir}`); + for (const s of skills) urls.push(`/${L.dir}skills/${s.name}`); + } const sitemap = '\n' + '\n' + - urls.map(u => ` ${SITE_URL}${u}${today}weekly${u === '/' ? '1.0' : '0.7'}`).join('\n') + + urls.map(u => ` ${SITE_URL}${u}${today}weekly${u === '/' ? '1.0' : (u.endsWith('/') ? '0.8' : '0.7')}`).join('\n') + '\n\n'; writeFileSync(join(DIST, 'sitemap.xml'), sitemap); @@ -643,8 +744,8 @@ function build() { '/styles.css\n Cache-Control: public, max-age=31536000, immutable\n' + '/app.js\n Cache-Control: public, max-age=31536000, immutable\n'); - const pages = 2 + skills.length * 2; - console.log(`✅ 生成 ${pages} 个页面:中/英首页 + ${skills.length} 个 skill × 2 语言详情页 → ${DIST}`); + const pages = LANGS.length * (1 + skills.length); + console.log(`✅ 生成 ${pages} 个页面:${LANGS.length} 语言(${LANGS.map(l => l.code).join('/')})× (首页 + ${skills.length} 个 skill 详情页) → ${DIST}`); } build();