Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ bun run typecheck
# 如果更改影响运行逻辑,执行端到端验证或 bun run test
```

### i18n 变更(翻译质量/抽查)

如果 PR 涉及 i18n 文案(尤其是 `settings` / `dashboard` / `myUsage`),请遵循:
- 规则说明:`docs/i18n-translation-quality.md`
- PR Checklist:`docs/i18n-pr-checklist.md`

CI 会在 PR 上运行 `Docker Build Test`(见 `.github/CI_CD_SETUP.md`)。如需验证容器构建,可本地执行:

```bash
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
73 changes: 73 additions & 0 deletions docs/edge-runtime-process-once.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Fix: Edge Runtime `process.once` build warning

## 背景

`next build` 过程中出现 Edge Runtime 不支持 Node API 的告警:`process.once`。

### 复现基线(修复前)

在修复前的版本(例如 tag `v0.4.1`)上运行 `bun run build` 可看到 Edge Runtime 不支持 Node API 的告警,其 import trace 包含:

```text
A Node.js API is used (process.once) which is not supported in the Edge Runtime.
Import traces:
./src/lib/async-task-manager.ts
./src/lib/price-sync/cloud-price-updater.ts
./src/instrumentation.ts
```

相关导入链路(import trace)包含:

- `src/lib/async-task-manager.ts`
- `src/lib/price-sync/cloud-price-updater.ts`
- `src/instrumentation.ts`

## 变更

- `AsyncTaskManager`:
- 在 `process.env.NEXT_RUNTIME === "edge"` 时跳过初始化,避免触发 `process.once` 等 Node-only API。
- `cloud-price-updater`:
- 移除对 `AsyncTaskManager` 的顶层静态 import。
- 在 `requestCloudPriceTableSync()` 内部按需动态 import `AsyncTaskManager`,并在 Edge runtime 下直接 no-op。

## 验证

- `bun run lint`
- `bun run typecheck`
- Targeted coverage(仅统计本次相关文件):
- `bunx vitest run tests/unit/lib/async-task-manager-edge-runtime.test.ts tests/unit/price-sync/cloud-price-updater.test.ts --coverage --coverage.provider v8 --coverage.reporter text --coverage.include src/lib/async-task-manager.ts --coverage.include src/lib/price-sync/cloud-price-updater.ts`
- 结果:All files >= 90%(Statements / Branches / Functions / Lines)
- `bun run build`
- 结果:不再出现 Edge Runtime `process.once` 相关告警

## 回滚

如需回滚,优先按提交粒度回退(以 commit message 为准):

- `fix: skip async task manager init on edge`
- `fix: avoid static async task manager import`
- `test: cover edge runtime task scheduling`

定位对应提交(示例):

```bash
git log --oneline --grep "fix: skip async task manager init on edge"
git log --oneline --grep "fix: avoid static async task manager import"
git log --oneline --grep "test: cover edge runtime task scheduling"
```

## 备选方案(若回归)

如果未来 Next/Turbopack 的静态分析行为变化导致告警回归,可将 Node-only 的 signal hooks 拆分到 `*.node.ts`(例如 `async-task-manager.node.ts`),并仅在 `NEXT_RUNTIME !== "edge"` 的分支里动态引入。

## 快速定位(避免文档漂移)

```bash
rg -n "process\\.once" src/lib/async-task-manager.ts
rg -n "NEXT_RUNTIME|NEXT_PHASE" src/lib tests
rg -n "requestCloudPriceTableSync" src/lib/price-sync/cloud-price-updater.ts tests/unit/price-sync/cloud-price-updater.test.ts
```

## 备注

`.codex/plan/` 与 `.codex/issues/` 属于本地任务落盘目录,不应提交到 Git。
36 changes: 36 additions & 0 deletions docs/i18n-pr-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# i18n PR checklist

> 中文对照版: [i18n-pr-checklist.zh-CN.md](i18n-pr-checklist.zh-CN.md)

This checklist is for changes that affect i18n messages, especially `settings`, `dashboard`, and `myUsage`.

## Required (automation)

- [ ] Run placeholder audit (scoped):
- `bun run i18n:audit-placeholders`
- [ ] If the PR is meant to eliminate placeholders, ensure fail mode is clean:
- `bun run i18n:audit-placeholders:fail`
- [ ] Run messages no-emoji audit (fail mode):
- `bun run i18n:audit-messages-no-emoji:fail`
- [ ] Run unit tests relevant to i18n/settings split:
- `bunx vitest run tests/unit/i18n/settings-split-guards.test.ts`
- `bunx vitest run tests/unit/i18n/settings-index-modules-load.test.ts`

## Required (review evidence)

- [ ] Include in PR description:
- the audit output diff (before/after) or a short summary (counts by locale + key modules)
- any allowlist changes with reasons (keep allowlist minimal and auditable)

## Required (manual spotcheck)

For at least `ja` and `zh-TW`:
- [ ] Settings pages (key areas): provider list, provider form, request filters, notifications
- [ ] Dashboard key widgets
- [ ] My Usage page

Attach screenshots (or provide a local path) for the key pages above.

## Rules to follow

See `docs/i18n-translation-quality.md` for R1/R2/R3 rules and allowlist conventions.
36 changes: 36 additions & 0 deletions docs/i18n-pr-checklist.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# i18n PR 检查清单

> English: [i18n-pr-checklist.md](i18n-pr-checklist.md)

此清单适用于会影响 i18n messages 的变更,尤其是 `settings`、`dashboard`、`myUsage`。

## 必做(自动化)

- [ ] 运行 placeholder 审计(scoped):
- `bun run i18n:audit-placeholders`
- [ ] 若该 PR 目标是清零 placeholders,确保 fail 模式无命中:
- `bun run i18n:audit-placeholders:fail`
- [ ] 运行 messages no-emoji 审计(fail 模式):
- `bun run i18n:audit-messages-no-emoji:fail`
- [ ] 运行与 i18n/settings split 相关的单元测试:
- `bunx vitest run tests/unit/i18n/settings-split-guards.test.ts`
- `bunx vitest run tests/unit/i18n/settings-index-modules-load.test.ts`

## 必做(Review 证据)

- [ ] 在 PR 描述中包含:
- 审计输出 diff(before/after)或简短摘要(按 locale 统计 + 关键模块)
- 如有 allowlist 变更,说明原因(保持 allowlist 最小且可审计)

## 必做(人工抽查)

至少覆盖 `ja` 与 `zh-TW`:
- [ ] Settings 页面(关键区域):provider list、provider form、request filters、notifications
- [ ] Dashboard 关键组件
- [ ] My Usage 页面

为上述关键页面附上截图(或提供本地路径)。

## 需要遵守的规则

参见 `docs/i18n-translation-quality.md` 获取 R1/R2/R3 规则与 allowlist 约定。
68 changes: 68 additions & 0 deletions docs/i18n-pr-evidence-2026-01-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# i18n no-emoji / docs zh evidence (2026-01-11)

This document is intended to be copy-pasted into a PR description.

## Summary

- Emoji cleanup (messages JSON):
- Before: 20 strings contained emoji (top files: `provider-chain.json`, `settings/data.json` across locales)
- After: 0 hits from `rg -n --pcre2 "\\p{Extended_Pictographic}" messages`
- Placeholder audit (zh-CN equality placeholders): OK
- Quality gates: `lint` / `typecheck` / `test` / `build` all pass

## Emoji cleanup details (messages JSON)

Key locations that were cleaned (keys unchanged, only values updated):
- `messages/<locale>/provider-chain.json`
- `provider-chain.timeline.circuitTriggered`
- `provider-chain.timeline.systemErrorNote`
- `messages/<locale>/settings/data.json`
- `settings.data.import.warningMerge`
- `settings.data.import.warningOverwrite`

Commands:
- Before/after scan:
- `rg -n --pcre2 "\\p{Extended_Pictographic}" messages`
- Optional structured listing (prints masked preview, no emoji characters):
- `node scripts/audit-messages-emoji.js --format=tsv`

## Placeholder audit (R1)

- `bun run i18n:audit-placeholders:fail`
- Expected output:
- `OK: no zh-CN placeholder candidates found in split settings.`

## No-emoji gate (R4)

- Script (codepoints only, no emoji printing):
- `bun run i18n:audit-messages-no-emoji:fail`
- Regression test (part of `bun run test`):
- `tests/unit/i18n/audit-messages-no-emoji-script.test.ts`

## Full regression commands

- `bun run lint`
- `bun run typecheck`
- `bun run test`
- `bun run build`

## Related commits (local)

- `564ab845` chore: add messages emoji audit script (I18NE-010)
- `aaa9fc7d` fix: remove emoji from messages warnings (I18NE-040)
- `80d20686` test: add messages no-emoji audit gate (I18NE-050)
- `2ee38f59` docs: add zh-CN i18n docs (I18NE-020)
- `44eeb5e9` docs: add messages no-emoji rule (I18NE-060)
- `92ebaf0e` chore: run full regression checks (I18NE-070)

## Manual spotcheck (ja / zh-TW)

Due to environment limitations (no GUI/browser automation in this run), screenshots are not attached here.

Recommended steps:
1. Start dev server: `bun run dev` (port 13500)
2. Open pages for both `ja` and `zh-TW` locales:
- Settings: `/settings` (providers list/form, request filters, notifications)
- Dashboard: `/dashboard` (key widgets)
- My Usage: `/my-usage`
3. Attach screenshots to the PR (or provide local file paths) and label each with locale + route.
37 changes: 37 additions & 0 deletions docs/i18n-settings-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# i18n settings split

> 中文对照版: [i18n-settings-split.zh-CN.md](i18n-settings-split.zh-CN.md)

This repository splits `messages/<locale>/settings.json` into smaller JSON chunks under `messages/<locale>/settings/`.

## Layout
- `messages/<locale>/settings/*.json`: settings top-level object parts
- `messages/<locale>/settings/strings.json`: top-level string keys that belong directly under `settings`
- `messages/<locale>/settings/providers/*.json`: `settings.providers` object parts
- `messages/<locale>/settings/providers/strings.json`: provider-level string keys
- `messages/<locale>/settings/providers/form/*.json`: `settings.providers.form` object parts
- `messages/<locale>/settings/providers/form/strings.json`: provider form string keys

Runtime composition happens in `messages/<locale>/settings/index.ts` and is imported by `messages/<locale>/index.ts`.

## Verification
- Translation quality rules and audit commands:
- `docs/i18n-translation-quality.md`

- Sync keys across locales (canonical: zh-CN):
- `node scripts/sync-settings-keys.js`

- Unit tests:
- `bun run test`

- Scoped coverage for split-related modules:
- `bunx vitest run --coverage --coverage.include=scripts/sync-settings-keys.js --coverage.include=messages/**/settings/index.ts`

- Typecheck:
- `bun run typecheck`

- Lint:
- `bun run lint`

- Production build:
- `bun run build`
39 changes: 39 additions & 0 deletions docs/i18n-settings-split.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# i18n settings split(拆分说明)

> English: [i18n-settings-split.md](i18n-settings-split.md)

本仓库将 `messages/<locale>/settings.json` 拆分为更小的 JSON 文件,存放在 `messages/<locale>/settings/` 目录下。

## 目录结构(Layout)

- `messages/<locale>/settings/*.json`: settings 顶层对象的各个子模块
- `messages/<locale>/settings/strings.json`: 直接属于 `settings` 顶层的字符串 key
- `messages/<locale>/settings/providers/*.json`: `settings.providers` 对象拆分后的子模块
- `messages/<locale>/settings/providers/strings.json`: provider 级别的字符串 key
- `messages/<locale>/settings/providers/form/*.json`: `settings.providers.form` 对象拆分后的子模块
- `messages/<locale>/settings/providers/form/strings.json`: provider form 的字符串 key

运行时拼装发生在 `messages/<locale>/settings/index.ts`,并由 `messages/<locale>/index.ts` 引入。

## 验证(Verification)

- 翻译质量规则与审计命令:
- `docs/i18n-translation-quality.md`

- 跨 locale 同步 key(canonical: zh-CN):
- `node scripts/sync-settings-keys.js`

- 单元测试:
- `bun run test`

- 针对 split 相关模块的 scoped coverage:
- `bunx vitest run --coverage --coverage.include=scripts/sync-settings-keys.js --coverage.include=messages/**/settings/index.ts`

- Typecheck:
- `bun run typecheck`

- Lint:
- `bun run lint`

- Production build:
- `bun run build`
64 changes: 64 additions & 0 deletions docs/i18n-translation-quality.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# i18n translation quality rules (R1/R2/R3)

> 中文对照版: [i18n-translation-quality.zh-CN.md](i18n-translation-quality.zh-CN.md)

This document defines the **scope** and **executable rules** for i18n translation quality in this repo.
Downstream scripts and review checklists should follow this document as the source of truth.

## Scope

Must-translate scope (at least):
- `settings` (split settings messages under `messages/<locale>/settings/`)
- `dashboard` (`messages/<locale>/dashboard.json`)
- `myUsage` (`messages/<locale>/myUsage.json`)

Locales: `zh-CN` is canonical. Other supported locales: `en`, `ja`, `ru`, `zh-TW`.

## Rule R1: No zh-CN placeholders in non-canonical locales

For any non-canonical locale:
- If a leaf string **equals** the `zh-CN` leaf string at the same key path, and the `zh-CN` value contains Han characters, it is treated as a **placeholder candidate**.
- Placeholder candidates should be **fixed** (translated), or **explicitly allowlisted** with a documented reason.

Executable check:
- `bun run i18n:audit-placeholders`
- To fail the command on any findings: add `--fail`.
- `bun run i18n:audit-placeholders:fail`

Allowlist (auditable, minimal):
- `scripts/audit-settings-placeholders.allowlist.json`
- Supported filters: `key`, `keyPrefix`, `keyRegex`, `valueRegex`, plus `glossary` terms.

## Rule R2: Placeholders/tokens must be preserved

When updating translations, **do not change**:
- keys / JSON structure
- placeholder tokens (e.g. `{name}`, `{count}`, `{resetTime}`)
- URL / command snippets unless intentionally translated and verified safe

Recommended verification:
- unit tests under `tests/unit/i18n/`
- spot-check affected UI pages for the locale (see the PR checklist)

## Rule R3: Glossary and consistent terminology

Maintain a short glossary for terms that should be consistent across locales (brand, model names, product terms).

Initial glossary (expand as needed, but keep it minimal and reviewed):
- Provider / Model / API / HTTP/2
- Claude / OpenAI / Codex (names should not be translated)

## Rule R4: No emoji in messages JSON

`messages/**/*.json` must not contain emoji characters.

Executable check:
- `bun run i18n:audit-messages-no-emoji:fail`

Notes:
- The audit output prints file path + key path + Unicode codepoints (without printing emoji characters).

## Notes

- Prefer fixing translations over expanding allowlists.
- Every allowlist entry must have a clear reason in the allowlist file (and ideally referenced in the PR description).
Loading
Loading