Skip to content

[UX-D] 術語與文案統一:正規用詞、錯誤中文化、格式收斂 (#46) - #53

Merged
poterpan merged 20 commits into
mainfrom
ux/46-terminology
Aug 30, 2026
Merged

poterpan merged 20 commits into
mainfrom
ux/46-terminology

Conversation

@poterpan

Copy link
Copy Markdown
Owner

Closes #46

UX 健檢批次 D(術語與文案統一),15 個 task、17 個 commits。這批跑在最後是刻意的:它幾乎全是跨檔字串掃描,而 UX-B(#44)與 UX-C(#45)會重寫 Dashboard.tsx、Payments.tsx、Manage.tsx、Settings.tsx、handler.ts、web/App.tsx——搶先做會漏掉那些檔案,或被它們重新引入舊字串。

正規用詞(§A 契約)

舊 新
核准 驗證(動作)/已驗證(狀態)/審核(流程)
paid 顯示為「已繳」 已繳待驗(表頭空間不足處用「待驗」)
本期 此期/實際期別
開帳 開繳
支付渠道 繳費渠道(表格短欄名「渠道」是合法簡稱)
帳單頻道 繳費頻道
使用者 成員
後台/成員面混用 後台=期別,成員面=月份

兩個 P0

  • P0-7「移除(已退訂)」→「移除(訂閱已暫停/已取消)」——原文案讓管理員以為那些人主動退訂,實際條件是訂閱狀態不是 active,包含被 CSV 匯入設為 FALSE 而暫停的人,兩者處理方式完全不同。
  • P0-8 已由 [UX-C] 成員回饋迴路 #45 的 payCommand(proofEnabled) 工廠修掉,本批次依計劃跳過。

行為相鄰的改動(有測試)

  • D14 後台可觸及的錯誤訊息中文化(20 個 404 + 16 處)
  • D15 InvalidPaymentTransition 改中文,paymentId/to 保留給日誌
  • D11 顯示層 enum 對映:payments.source、subscriptions.status、plans.provider 標籤
  • D19 金額千分位——同一筆帳單,成員在 Discord 看到 NT$1,258、繳費頁看到 NT$1258

刻意保留英文(§A.14)

period must be YYYY-MM(12 處)、billing_day must be 1..28 等純格式驗證維持英文,因為 UI 走不到:前端送的是 <input type="month"> 的輸出、min/max 已擋、或被 client-side validation 先攔(請填名稱)。routes/admin.ts 加了檔頭註解說明這是刻意的,免得後人以為沒掃乾淨而「修完」。

三個看似殘留、實則正確的保留

  1. billing-reconcile.test.ts 的 已繳者 是 fixture 的人名(與「加入者」「退訂者」同組角色暱稱),不是狀態標籤。
  2. 月份 in admin 正好是 §A.4 允許的兩行 CSV 說明(起算月份 講的是 start_date,不是期別)。
  3. 期別 in adapters/discord/ —— /發起繳費 是管理員專屬指令(isAdmin + default_member_permissions),§A.3 明訂用「期別」;且 option 的 name: "期別" 是 Discord interaction payload 的線路識別碼,改了指令就壞。計劃檔 Task 5 原本要求這裡歸零,但 §A 優先——這是刻意不改的。

一個刻意的不對稱(請勿「修正」)

工具列/卡片頭的開窗動作加 …(產生上傳連結…、新增成員…),但列內的 編輯/刪除/停用/啟用 不加——它們每列重複一次,而 UX-B 已把那些列在行動版變成卡片,多一個字元純粹是噪音。

標註而非改造(§A.15)

  • timezone 是死設定:parseSettings 讀它也存回,但沒有任何一處使用(日期全在 core/time.ts 寫死 Asia/Taipei)。保留而非刪除——刪掉會改 settings schema、破壞 env.test.ts 的往返斷言;後台也刻意沒有這個欄位(改了不會有效果的控制項比沒有更糟)。
  • plans.discord_role_id 不會自動發放或回收身分組,只用來在公告裡 @。欄位標籤改為明講。
  • 兩則寫死的訊息(綁定提示、個別催繳)加註為什麼還沒模板化。

驗收

八個歸零斷言全部通過(核准/本期/開帳/支付渠道/使用者/帳單頻道/已退訂/開始繳費)。
Worker 測試 426 → 431(D14/D15 各補測試);pnpm -r typecheck 綠;admin + web build 綠。
wrangler.toml 與 docs/deploy-state.md 零改動。

⚠️ 部署後必做

/繳費 與 /發起繳費 的指令描述有變更。Discord 的指令描述是註冊時寫死的——部署後必須到後台 → 設定 → 工具 → 註冊 Discord 指令按一次,否則成員看到的仍是舊描述。

審查註記

Codex 跨引擎審查將於開 PR 後送出。

「移除(已退訂)」會讓管理員以為那些人主動退訂了,但實際條件是
訂閱狀態不是 active——包含被暫停(CSV 匯入填 FALSE)與已取消兩種,
兩者的處理方式完全不同。改為「移除(訂閱已暫停/已取消)」。

P0-8(/繳費 指令描述的「可選」)已由 #45 的 payCommand 工廠修掉,
本批次依計劃跳過。
三個詞在同一組正規用詞裡,一次掃齊(§A.6、§A.7):

- 支付渠道 → 繳費渠道(導覽標籤、Card 標題、刪除確認、caption)共 6 處。
  表格短欄名「渠道」是 §A.6 明訂的合法簡稱,維持不動。
- 帳單頻道 → 繳費頻道(4 處)。兩個名字指的都是同一個
  discord_billing_channel_id,而設定頁的欄位標籤本來就叫「繳費頻道 ID」。
- 使用者備註 → 成員備註(1 處,與 MemberReview 的「成員備註:」對齊)。
  packages/** 的「使用者」歸零。

「夥伴」依 §A.7 保留——那是成員面的招呼語(web 的「嗨,{name}」與預設催繳模板),
稽核明確允許。
繳費詳情的「來源」原本直接印出 enum 值(user_slash / admin_manual / cron),
管理員要自己翻譯。新增 SOURCE_LABEL,沿用 Manage.tsx 的 CHANNEL_TYPE_LABEL
先例(Record + ?? raw fallback,未知值降級成自己)。

**顯示層而已**——DB 值、SQL、request body 一律沒動。

用詞說明:cron 標為「系統建立」而非「排程」,因為 billing.ts 的預設 source 也是
cron,發起繳費與重新同步都走它;user 標「Discord(舊版)」——今天沒有任何程式寫入
這個值,它是 schema 預設,只有舊資料才有。
同一筆帳單,成員在 Discord 看到 NT$1,258、在繳費頁看到 NT$1258。
Discord 端(adapters/discord/notify.ts)一直都有 toLocaleString,
只有這一頁沒有。

admin 半邊(Manage.tsx 的方案選單與月費欄)留待 Task 8 的並行工作結束後再補,
避免與正在改同一檔的工作衝突。
parseSettings 會讀它、也會原樣存回,但系統裡沒有任何一處使用——
所有日期都在 core/time.ts 寫死用 Asia/Taipei 計算。

保留而非刪除:刪掉會改動 settings schema,破壞 env.test.ts 斷言的
「存進去什麼、讀出來就是什麼」往返。後台也刻意沒有這個欄位——
一個改了不會有任何效果的控制項,比沒有控制項更糟。

要讓時區真的可設定,該改的是 core/time.ts,不是這一行。
D19 admin 半邊:方案選單與月費欄的 NT$ 金額補上 toLocaleString,
與 Discord、繳費頁一致。

D21:欄位標籤原本只寫「(通知 tag 用)」,容易被讀成系統會管理身分組。
實際上 plans.discord_role_id 只用來在公告裡 @ 那個身分組——
不會自動發放、也不會在退訂時回收。標籤改為明講這件事。
三件事的誠實解法是「把實情講出來」,而不是重建(§A.15):

- 設定頁「Discord 訊息文字」卡片原本讓人以為所有機器人訊息都能改,
  實際只有開繳/催繳/常駐繳費訊息三則。卡片說明改為明講,
  並在兩則寫死的訊息(綁定提示、個別催繳)上加註為什麼還沒模板化——
  要模板化就得改 settings schema,屬期別生命週期重構的範圍。
- README 補一行說明 timezone 是死設定。

測試維持 431,沒有任何斷言因註解而移動。
Task 15 的全域稽核抓到的殘留:UI 的標題在 P0-7 已改,README 還寫著舊的。
順帶把同一行的「已繳」補成「已繳待驗」(D2 的用詞)。
§A.10 的純格式收尾(Task 13):

- 規則 5:開窗的工具列/卡片頭動作補上 `…`
  (重新同步此期帳單…、收回此期開繳…、產生上傳連結…、手動補登…、
   新增成員…、新增訂閱…、新增方案…、新增渠道…)。
  列內的 編輯/刪除/停用/啟用 **刻意不加** —— 它們每列重複一次,
  UX-B 已把那些列在行動版變成卡片,多一個字元純粹是噪音。
- 規則 6:收回預覽的進度字 `計算中…` → `計算差異中…`,與同步預覽一致。
- 規則 4:SyncModal/RetractModal 兩則成功訊息補 `✓ ` 前綴。
- 規則 3:匯入結果的半形 `/` 改頓號;「會新增/暫停訂閱」標籤改全形 `/`。
- 規則 2:結帳日提示的 `29–31` en-dash 改 ASCII `29-31`。

行為零變動;worker 431 tests / 57 files 全綠。
D14/D15 的錯誤訊息中文化各補了測試(+5)。
**1. 被弱化的測試斷言**(discord-pay.test.ts)
掃描期別用詞時,斷言從 `已登記本期` 改成 `已登記` + /\d{4}-\d{2}/。
那個正規表達式匹配任何月份——回報錯月份的 bug 也會通過。
改為 `已登記 ${PERIOD}`,並實測:注入回報 2099-01 的 bug,測試確實會紅。

**2-5. 四處「UI 走不到」的宣稱其實走得到**
§A.14 允許那些錯誤訊息維持英文,前提是前端會先擋下來。Codex 抓到四個前提不成立:

- 每月結帳日的 min/max 只是提示,打 29 按儲存就會送出 → 補 client 驗證(含逾期天數、保存月數)
- CSV 起算日是自由文字框,打錯格式直接撞後端 → 改 type="date"(與 #44 B14 一致)
- 發起繳費的期別可以清空,invalid 只檢查金額 → 期別納入 invalid
- 手動補登與產生上傳連結的期別同樣可清空 → 兩處都補 PERIOD_RE 檢查

修的是「讓前提成立」而不是把訊息翻成中文——那些訊息本來就該是使用者看不到的。

測試維持 431。
@poterpan
poterpan merged commit 320c4c4 into main Aug 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UX-D] 術語與文案統一

1 participant