# PURO Portal i18n + Pricing Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Ship bilingual (zh/en) support across 5 portal pages (Landing, Docs, Login-narrative, Register-narrative, **new** Pricing) by mounting a dark-tech `PuroLocaleSwitcher` in each top nav and extracting all hard-coded Chinese into i18n keys with English translations. **Architecture:** - Reuse the existing `vue-i18n` infrastructure (`setLocale()`, `availableLocales`, `sub2api_locale` localStorage key). Only add portal-specific namespaces: `landing.*`, `docs.*`, `pricing.*`, `auth.narrative.*`. - The current admin `LocaleSwitcher.vue` uses Tailwind gray/dark palette that clashes with `.puro-page` dark-tech theme — build a new `PuroLocaleSwitcher.vue` styled with puro.css tokens (`--cyan`, `--bg-0`, `--border`, `--font-mono`), reusing the same `setLocale()` core. - Pricing page is ported from `docs/design-drafts/v2/Pricing.html` as a fidelity Vue component, i18n-native from commit one (no "extract later" debt). **Tech Stack:** Vue 3 + TS (` ``` - [ ] **Step 2: Verify component typechecks** Run: `pnpm run typecheck` (from `frontend/`) Expected: PASS, no new errors. - [ ] **Step 3: Commit** ```bash git add frontend/src/components/puro/PuroLocaleSwitcher.vue git commit -m "feat(i18n): add PuroLocaleSwitcher for portal pages" ``` --- ## Task 2: Mount switcher in `LandingView` nav **Files:** - Modify: `frontend/src/views/landing/LandingView.vue` (template nav block + script import; NO i18n text extraction in this task — that happens in Task 5) - [ ] **Step 1: Import the switcher** In ` ``` - [ ] **Step 2: Typecheck** Run: `pnpm run typecheck` Expected: PASS. - [ ] **Step 3: Commit** ```bash git add frontend/src/components/puro/PricingCalculator.vue git commit -m "feat(pricing): add PricingCalculator subcomponent" ``` --- ## Task 9: Build `PricingView` (i18n-native) + add route **Files:** - Create: `frontend/src/views/pricing/PricingView.vue` - Modify: `frontend/src/router/index.ts` (add `/pricing` route) - Modify: `frontend/src/i18n/locales/zh.ts` (add `pricing.*`) - Modify: `frontend/src/i18n/locales/en.ts` (add `pricing.*`) **Source:** `docs/design-drafts/v2/Pricing.html` — port verbatim, extract Chinese strings to keys. **Decisions locked:** - Header subkicker: ZH `// preview · 最终定价以开售为准` / EN `// preview · final pricing TBD at launch` - Calculator header pill: ZH `// estimated · 以实际计费为准` / EN `// estimated · for reference only` - Enterprise card → `mailto:contact@puro.im` - Binding card → `/register` router-link (no `/binding` page) - Tier CTAs → `/register` router-link - Final CTA `Docs` link → `/docs` **SOON chip:** before writing the template, the subagent audits the backend for these features (grep at `backend/`): 1. API Key monthly budget / 402 Payment Required → look for `budget` / `Payment Required` 2. Zero-log mode → look for `zero_log` / `zeroLog` 3. Priority scheduling → look for `priority` 4. RPM limits (60/120/300) → look for rate limiter 5. Subscription failover → look for `failover` / `cooling` For each feature NOT found: wrap the `
` with an extra chip `{{ $t('pricing.soonChip') }}` (chip = small pill, amber/muted). Add chip CSS in same scoped style. - [ ] **Step 1: Audit backend for advertised features** Run: `cd /Users/mini/Work/dev/sub2api && grep -ril -E "budget|zero_log|priority_schedul|failover|cooling" backend/ 2>/dev/null | head -20` Document which features are implemented; the rest get `SOON` chips. - [ ] **Step 2: Add `pricing` namespace to `zh.ts`** with structure: ```ts pricing: { hero: { kicker: '// pricing · 充多少 · 用多少 · 永不过期', previewPill: '// preview · 最终定价以开售为准', title1: '一次充值,', titleAccent: '全平台', title2: '通用', sub: '同一份积分可以用在 Claude / ChatGPT / Gemini 任意池上。我们把你的订阅额度变成真正的 API 余额 —— 相比官方 API 便宜 {discount}。', subDiscount: '至多 70%', underline: '余额永不过期 · 支持支付宝 / 微信 / USDT · 无隐藏订阅费' }, soonChip: 'SOON', tiers: { starter: { flag: 'STARTER', tierLabel: 'tier · 01', headline: '先尝尝鲜,跑通接入', credit: '充 $9.9 → 得 {credit} 积分 {bonus}', creditAmount: '$12', creditBonus: '+21%', discountTag: '相当于官方 API · 0.5 折起', cta: '充值 →', features: { allModels: '可用所有模型 / 所有池', oneKey: '{count} 个 API Key', oneKeyCount: '1', rpm60: '60 RPM 速率限制', log7: '基础日志(7 天保留)', noBYOS: '自带订阅接入', noTeam: '团队 / 多人协作' } }, pro: { flag: '◆ 推荐', tierLabel: 'tier · 02', headline: '个人重度用户 · 最划算', credit: '充 $29.9 → 得 {credit} 积分 {bonus}', creditAmount: '$45', creditBonus: '+50%', discountTag: '相当于官方 API · 3-7 折', cta: '立即充值 →', features: { allModels: '可用所有模型 / 所有池', threeKeys: '{count} 个 API Key · 独立预算', threeKeysCount: '3', rpm120: '120 RPM 速率限制', log30: '调用日志(30 天保留)', byos: '自带订阅接入(无限个)', failover: '多账号 failover 调度' } }, scale: { flag: '⚡ 限时 +100%', tierLabel: 'tier · 03', headline: '小团队 / 长跑项目', credit: '充 $99 → 得 {credit} 积分 {bonus}', creditAmount: '$198', creditBonus: '+100%', discountTag: '相当于官方 API · 2-5 折', cta: '充值 →', features: { proAll: '所有 Pro 能力', tenKeys: '{count} 个 API Key · 独立预算', tenKeysCount: '10', rpm300: '300 RPM 速率限制', log90: '调用日志(90 天保留)', priority: '请求优先级加权调度', community: 'Slack / Discord 群组支持' } }, custom: { flag: 'CUSTOM', tierLabel: 'tier · 04', headline: '自定义金额 · 按需充值', creditPrefix: '得约', bonusPrefix: '+', discountTag: '根据金额阶梯自动匹配折扣', cta: '定制充值 →', features: { noExpire: '积分永不过期', proAll: 'Pro 全部能力', tier: '阶梯 +21% ~ +100%', pay: '支付宝 / 微信 / USDT', slider: '拖动滑块预览赠送' } } }, custom: { enterprise: { title: 'Enterprise · 企业定制', desc: '专属订阅池、SLA、合规审计、私有化部署、发票结算。规模 >$500/月起可申请。', cta: '联系商务 →' }, binding: { title: '已有订阅?直接接入', desc: '有 Claude Max / ChatGPT Pro?免费注册后绑定,只为 PURO 路由费买单 —— 按次 {price}。', price: '$0.0008/request', cta: '接入我的订阅 →' } }, calc: { kicker: '// cost estimator', previewPill: '// estimated · 以实际计费为准', title: '算算你能省多少?', sub: '按你的使用场景,对比 PURO 和官方 API 的月度花费差。数字会根据你选的场景自动更新。', reqLabel: '日均请求数', tokLabel: '平均每请求 tokens', mixLabel: 'Claude 占比', monthlyTok: '月度 tokens 消耗', officialCost: '官方 API 价格', puroCost: 'PURO 价格(含 +50% 赠送)', savings: '节省', recLabel: '建议充值', recStarter: '≈ Starter 档够用', recPro: '≈ Pro 档 1 个月', recScale: '≈ Scale 档 · 1 个月' }, works: { kicker: '// works everywhere', title: '一个 key,所有工具通用', sub: '只要支持自定义 {baseUrl} 或 OpenAI / Anthropic API,都能直接接入 PURO。', baseUrl: 'base_url' }, faq: { kicker: '// frequently asked', title: '你可能想问的', noAnswer: '没找到答案?{contact} · 通常 2 小时内回复。', contact: '发邮件给我们 ↗', q1: 'PURO 和 API 中转站 / API 代理有什么不同?', a1: '中转站只是把官方 API 请求转一手,价格取决于你预付多少 balance。PURO 的不同是 —— 我们让你 {bold}。你原本就在付的 $20/月,不再只能在官网聊天里用,而是通过统一 API 喂给 Cursor、Claude Code、任何 SDK。同时我们也提供按量充值的官方 API 备用池,两种模式可以混用。', a1bold: '把已有的 Claude Pro / ChatGPT Plus 订阅变成 API', q2: '用订阅跑 API 会不会被封号?', a2: '我们会自动控制每个订阅的请求节奏,并在触发限流时把请求 failover 到池子里的其他订阅。实际上 PURO 的调用模式比你在官方客户端直接复制粘贴大段对话 {bold}。你绑定多个订阅时,单个账号的 RPM 会被压到足够安全的阈值内。另外所有凭证用 AES-256 加密存储,请求链路不经过第三方。', a2bold: '更不容易触发风控', q3: '积分会过期吗?可以退款吗?', a3: '{bold}你可以攒着慢慢用 —— 包括几个月都不用。首次充值 7 天内未产生任何调用可全额退款,之后按剩余积分 85% 比例退。详见退款政策。', a3bold: '积分永不过期。', q4: '支持哪些支付方式?', a4: '国内:支付宝 · 微信支付。国际:Stripe 信用卡 · USDT (TRC20 / ERC20) · PayPal。企业充值支持 Invoice 对公打款,人民币开票。', q5: '一个 PURO 账号可以绑定多少个订阅?', a5Starter: 'Starter 档:不支持绑定自带订阅', a5Pro: 'Pro 档及以上:无限制,你可以把 10 个 ChatGPT Plus + 3 个 Claude Pro 一起绑上去,统一调度', a5Enterprise: 'Enterprise:支持跨团队共享池,按组织维度隔离', q6: '如果某个订阅触发限流了会怎样?', a6: 'PURO 的调度器会把受限的订阅自动标记为 cooling 状态,暂时从池子里摘除。同一请求会立刻被 failover 到池内其他健康订阅上 —— 调用方通常 {bold}。你可以在 Dashboard 看到每个订阅的当前状态和剩余配额。', a6bold: '感受不到中断', q7: '计费精度?超量会怎么办?', a7: '按实际 token 数 + 模型单价计费,精度到 4 位小数。每个 API Key 可设置独立月度预算,达到后 402 Payment Required,不会继续扣费。账户总余额不足时同样会返回 402,且 Dashboard 有 80% / 95% 两级提醒邮件。', q8: '数据会被用于训练吗?', a8: '{bold}所有请求仅用于路由转发,不入库、不留存内容(仅保留元数据如模型、token 数、延迟,用于计费和日志)。Pro 档及以上可选开启"零日志模式",我们连请求 ID 都不记录。', a8bold: '不会。', q9: '可以私有化部署吗?', a9: 'Enterprise 档支持 Docker / K8s 私有化部署,控制面和数据面可以分开。授权按年订阅,包含升级和技术支持。', q10: '支持哪些模型?会跟进新模型吗?', a10: '当前覆盖 Claude(Sonnet 4.5 / Opus 4 / Haiku 4.5)、ChatGPT(GPT-5 / GPT-5 Codex / GPT-4.1)、Gemini(2.5 Pro / 2.5 Flash)。每当官方发布新模型,我们通常在 {bold}。完整模型列表见文档。', a10bold: '24 小时内上线' }, finalCta: { kicker: '// ready to start', title: '5 分钟,拿到你第一个 sk-puro-* key', subtitle: '绑定你的第一个订阅即可开始。', ctaPrimary: '免费注册 →', ctaDocs: '查看文档' } } ``` **Note:** The zip's final CTA contains `注册送 $5 测试积分` — DROP this line per Stage 1 decision (no $5 bonus). The subtitle above is pruned. - [ ] **Step 3: Mirror `pricing` namespace in `en.ts`** Translation guidelines: - Hero title: `"Top up once," / "unlimited across" / "all platforms"` - Hero sub: `"The same credits work across Claude / ChatGPT / Gemini pools. We turn your subscription into real API balance — {discount} cheaper than the official API."` - Tier CTAs: `"Top up →"` / `"Buy Pro →"` / `"Top up →"` / `"Custom top-up →"` - Tier flags: `"STARTER"` / `"◆ RECOMMENDED"` / `"⚡ LIMITED +100%"` / `"CUSTOM"` - FAQ answers: professional/concise tone, keep technical terms English - [ ] **Step 4: Write `PricingView.vue`** Structure: ```vue ``` **Subagent execution note:** This task is large. Full template is ~400 lines of Vue. Subagent should: 1. Open `docs/design-drafts/v2/Pricing.html` in one tab 2. Open the target `PricingView.vue` being written 3. Copy each section (hero → tier grid → custom row → calc → works → faq → final-cta), replacing raw Chinese with `$t(...)` lookups per the schema in Step 2 4. Keep all SVG/HTML structure verbatim 5. Apply the SOON chip to any unimplemented feature per Step 1 audit results 6. Remove the $5 bonus line from final CTA - [ ] **Step 5: Add `/pricing` route** Modify `frontend/src/router/index.ts`. Add new route entry (public, no auth guard): ```ts { path: '/pricing', name: 'pricing', component: () => import('@/views/pricing/PricingView.vue'), meta: { requiresAuth: false, title: 'Pricing · PURO AI' } } ``` Add this near the `/docs` route (public portal section). - [ ] **Step 6: Add `定价 / Pricing` link to LandingView nav** Modify `LandingView.vue` `.nav-links` block: ```vue ``` (Landing's Pricing link was added as part of Task 3's nav update for Docs; Landing gets it here.) - [ ] **Step 7: Typecheck + build** Run: `pnpm run typecheck && pnpm run build` Expected: PASS. - [ ] **Step 8: Commit** ```bash git add frontend/src/views/pricing/ frontend/src/router/index.ts frontend/src/views/landing/LandingView.vue frontend/src/i18n/locales/zh.ts frontend/src/i18n/locales/en.ts git commit -m "feat(pricing): add PricingView with bilingual i18n + nav link" ``` --- ## Task 10: Verification + PR + deploy **Files:** none changed - [ ] **Step 1: Run full typecheck + build** ```bash cd frontend pnpm run typecheck pnpm run build ``` Expected: both PASS. - [ ] **Step 2: Scan for leftover hard-coded Chinese in portal views** ```bash cd /Users/mini/Work/dev/sub2api grep -rnP "[\x{4e00}-\x{9fa5}]" frontend/src/views/landing/ frontend/src/views/docs/ frontend/src/views/pricing/ 2>/dev/null | grep -v "^.*://" | grep -vE "" ``` Expected: empty output (only things that should remain are comments, which this grep filters). - [ ] **Step 3: Start preview and manually verify** ```bash cd frontend pnpm run preview ``` Open in browser (http://localhost:4173): - `/` — Landing: switcher in top-right, click `EN` → all text flips to English, refresh → stays English - `/pricing` — Pricing: 4 tiers render, calculator sliders work, FAQ accordions open, switcher works - `/docs` — Docs: tables render, copy-code works, switcher works - `/login` — narrative panel + form, switcher top-right - `/register` — narrative panel + form, switcher top-right For each page: toggle EN ↔ ZH at least twice, confirm no flashes of untranslated Chinese. - [ ] **Step 4: Stop preview** Ctrl-C the preview server. Verify no zombie processes: ```bash pgrep -f "vite.*preview" ``` Expected: no output. If any: `pkill -f "vite.*preview"`. - [ ] **Step 5: Push branch and open PR** ```bash git push -u origin feat/portal-i18n-pricing gh pr create --title "feat: PURO portal i18n (zh/en) + Pricing page" --body "$(cat <<'EOF' ## Summary - Puro-themed `PuroLocaleSwitcher` mounted in Landing/Docs/Login/Register top nav - Full i18n extraction for LandingView / DocsView / Login & Register narrative panels (zh + en) - New `/pricing` page ported from design zip, i18n-native, with preview pricing pill + SOON chips for unshipped features - Nav adds 定价 / Pricing link on Landing + Docs ## Test plan - [ ] Typecheck + build pass - [ ] Toggle EN/ZH on /, /pricing, /docs, /login, /register — all text switches - [ ] Refresh persists locale (localStorage `sub2api_locale`) - [ ] Pricing calculator sliders update live; custom tier bonus updates - [ ] Admin pages (`/dashboard`, `/admin/*`) unaffected — no CSS regressions 🤖 Generated with [Claude Code](https://claude.com/claude-code) EOF )" ``` - [ ] **Step 6: Merge when CI green** ```bash gh pr merge --squash --delete-branch ``` - [ ] **Step 7: Verify production deploy** ```bash curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/ curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/pricing curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/docs ``` Expected: `200 200 200`. - [ ] **Step 8: Cleanup worktree** ```bash cd /Users/mini/Work/dev/sub2api git worktree remove ../sub2api-portal-i18n ``` --- ## Appendix: Translation style guide (EN) - **Register:** tech-product, concise, no marketing fluff - **Technical terms:** keep English (`OAuth`, `SDK`, `API key`, `RPM`, `base_url`, `tokens`) - **Brand tone:** PURO speaks to developers first, so answers in FAQ stay factual, not salesy - **Punctuation:** English full stops / commas (not `,` or `。`) - **Numbers:** keep format from zh (e.g., `$29.9`, `$198`) ## Appendix: Key guarantees - All 5 pages continue to render correctly in zh after extraction (regression check at Task 10 Step 3) - `setLocale()` remains the single source of truth — no custom storage added - `PuroLocaleSwitcher` reuses `setLocale()` imports; does not duplicate i18n plumbing - No changes to admin pages, AppHeader, or existing `LocaleSwitcher.vue` (decoupled)