adventure-table

M02 — 開發設計方針

Phase:M02 — Traditional Chinese / English Localization
類型:M Phase(Modification / Maintenance Phase)
插入時點:M01-C — SCAG / GoS Background Expansion closeout 後,暫停 M01;M02 closeout 後回到 M01-D。
本文件定義 M02 的具體實作契約:locale state、presentation boundary、localizable field policy、localized content resolver、resource layout、API / DTO 接線、translation authoring pipeline、搜尋與 completeness gate。完成後必須滿足 實作規格.md;驗收流程見 測試指南.md

狀態:M02 已 closeout(2026-08-31)。M02-A~M02-H 全部完成,下一步為 M01-D。 Closeout evidence:M02-C_CLOSEOUT.mdM02-D_CLOSEOUT.mdM02-E_CLOSEOUT.mdM02-F_CLOSEOUT.mdM02-G_CLOSEOUT.mdM02-H_CLOSEOUT.md

最後更新:2026-08-31


1. 設計目標

M02 不是把目前頁面上的英文字串逐一替換成中文,而是建立可長期維護的 localization foundation,使後續新增 content / product surface 不再產生 English-only presentation debt。

核心設計目標:

  1. Rules identity 與 presentation language 分離。
  2. locale 是 browser presentation preference,不屬於 Character / Draft / Campaign domain state。
  3. Server authoritative rules 不因 locale 改變。
  4. 目前 user-visible 的 system / rules text 都能依目前 locale render。
  5. StableKey、Builder choice identity、Build refs、State refs 永遠不因翻譯而改變。
  6. 翻譯 scope 由 field-level visibility policy 決定,不以整個 content category 一刀切。
  7. 繁中與英文都具備 completeness gate;production 不以 fallback 掩蓋缺翻譯。
  8. M02 只支援 zh-TW / en,不要預先設計多語 marketplace 或 user-authored language pack。

2. Locale domain contract

2.1 Supported locale

正式 type / enum 僅允許:

zh-TW
en

禁止在程式中用自由字串任意傳 locale。

2.2 Default / persistence

第一版:

locale storage key 必須由單一 module 定義,不得不同頁面各自 hardcode。

2.3 Runtime state

Frontend 提供單一全站 locale provider / context / store,頁面與 component 都從同一 runtime locale 取得目前語言。

切換 locale:

user action
→ update runtime locale
→ persist browser preference
→ React rerender

不得:

locale switch
→ window.location.reload()

也不得呼叫任何 Draft / Character mutation API。

2.4 HTML language

目前 locale 改變時同步更新 document language metadata,例如 <html lang>,供 accessibility / browser semantics 使用。

2.5 Query / cache boundary

任何 cache 若保存 locale-dependent presentation:

不得讓 zh-TW response 被 en 頁面沿用,反之亦然。


3. Translation boundary

M02 必須明確區分三類文字。

3.1 UI copy

例如:

全部走 UI translation resources,不再在 feature component 內新增 user-visible hardcoded English / Chinese literal。

3.2 Rules / content presentation

例如:

這些以 StableKey 或其他穩定 content identity 解析 localized presentation。

3.3 User-authored text

例如:

不得因切換 locale 自動翻譯或改寫。


4. Localizable field policy

4.1 Policy 是 scope 的單一事實來源

M02-C 必須建立正式 localizable field policy,供 M02-D / E / F / G 與後續 Phase 共用。

政策至少能回答:

pack / kind / field-path
→ localizable?
→ currently user-visible?
→ required locales
→ product surface / reason

具體可用 schema、typed table、JSON policy 或等價可機器讀取形式;不能只存在於人的印象或散落的測試清單。

4.2 Required 的判準

M02 closeout 當下:

field 必須翻譯,當且僅當它在目前已存在的產品畫面/正常使用流程中會被顯示給使用者。

這是 field-level,不是 category-level。

例如現有 Inventory selector 會列出 SRD magic item name

item.name → required

若當時沒有 UI 顯示該 item 的完整 description:

item.desc → not required yet

未來 M01-I 或其他 Subphase 新增畫面首次顯示 item.desc 時,該 Subphase 必須同步補齊所有 supported locales。

4.3 Internal / machine-only fields

下列不因是 string 就自動翻譯:

4.4 Policy change guard

新增 product surface 時,若讓既有 field 從 not user-visible 變成 required


5. Localized content model

5.1 Canonical content 不因 locale 複製

Canonical runtime pack 仍維持:

data/<pack>/...

例如:

srd5.1:spell:fireball
phb2014:background:acolyte
scag:background:city-watch
gos:background:marine

不得建立:

srd5.1-zhTW:spell:fireball
zh-TW:srd5.1:spell:fireball

5.2 Localization overlay

每個正式 content pack 可有 locale overlay;建議 layout:

data/<pack>/locales/
├── en.json
└── zh-TW.json

資料量大時可按 category 拆檔,例如:

data/srd5.1/locales/zh-TW/
├── spells.json
├── features.json
└── ...

具體拆分可依資料量調整,但必須滿足:

5.3 English canonical policy

若 canonical source 已是英文,en presentation 可以由 canonical field直接提供或經 overlay 正規化;但對 runtime caller 必須呈現一致的 localized resolver contract,不得讓 component 猜「這個 pack 的英文是不是自己讀 canonical name」。

5.4 Supported presentation fields

Resolver至少能支援:

是否 required 仍由 localizable field policy 決定。


6. Localized content resolver

建立單一 localization resolver / presentation service,不讓各 feature 自己拼語言邏輯。

概念責任:

StableKey + field + locale
→ canonical entry
→ localizable field policy
→ localized overlay / canonical en
→ localized presentation

resolver 應能提供至少:

缺 translation 的處理:

可保留 defensive fallback 避免程式 crash,但 fallback 發生必須可被測試與診斷偵測,不能讓 completeness gate 通過。


7. Server / DTO presentation contract

目前 Builder / Sheet 流程存在 server-generated name / label / message。M02 必須清理「server 先把英文 presentation 固化,再交給 frontend」的路徑。

允許兩種模式之一,實作時選一套並保持一致:

模式 A:Server localized DTO

request 帶明確 presentation locale,server 依 locale resolve name / label / description。

要求:

模式 B:Identity-rich DTO + frontend resolver

server DTO 優先提供 StableKey / machine identity,frontend 透過已載入 localization data render。

要求:

M02 不要求所有 DTO 完全移除 display text,但任何 user-visible rules label 必須有足夠 identity 可正確切換語言。


8. Validation / error localization

8.1 Machine-readable first

Builder validation / domain errors 優先依:

code
severity
path
related_refs

作為穩定 identity。

不能把英文 message 當唯一 error identity。

8.2 UI presentation

Frontend 顯示時以 error code / structured metadata取得目前 locale 文案。

若 server 仍需回傳 message:

8.3 Dynamic values

錯誤訊息含數值、名稱、level、choice 等動態值時,使用 structured interpolation;其中 rules entity 名稱亦需走 localized resolver。


9. Roleplay suggestion identity

這是 M02 必須修正的既有 localization debt。

系統提供的 Background roleplay suggestion 不應只靠 raw English sentence 當 identity。

應提供穩定 suggestion identity,例如 conceptually:

<background-stable-key>:roleplay:<field>:<suggestion-id>

或等價 deterministic id。

系統 suggestion:

identity
→ locale-specific presentation

使用者自己輸入的文字:

raw user text
→ 永遠原樣保存

若使用者「採用系統 suggestion」後希望能隨 locale 切換,持久化模型必須保留足夠 identity,不得只能留下 translated/raw display string。

既有已保存且只剩 raw text 的資料不做猜測式 migration;視為 user-authored / legacy text 保留原樣。


10. Search / sort contract

10.1 顯示

搜尋結果只顯示目前 locale 的 presentation;繁中模式不要為了搜尋 alias 額外並排英文名稱。

10.2 Cross-locale alias

允許目前 locale 的搜尋 index 同時接受另一正式 locale 名稱作 alias。

例如:

locale = zh-TW
query = fireball
→ result displays 火球術

10.3 Sort

需要依名稱排序的 UI,應依目前 locale display name 進行 locale-aware sort;不得用 StableKey / index 假裝 alphabetical presentation sort。

10.4 Search identity

搜尋命中不改變 persisted selection;最終保存仍是 StableKey。


11. Translation glossary

建立正式 D&D 5e 2014 terminology glossary / translation contract。

用途:

不得把 glossary 做成 runtime regex replace engine。

至少涵蓋:

11.1 Existing Traditional Chinese reference input

docs/暫用規則資訊/ 的繁中譯名是 glossary 的 priority reference input,而不是 runtime source。

M02-C glossary 至少保存:

English term / canonical name
chosen zh-TW
legacy/reference zh-TW(有差異時)
reference source
optional decision note

若決定不採用既有 reference 譯名,必須有可追溯 decision note;不需要為每個 reference Markdown occurrence 建立第二套人工同步表。

M02 closeout 後 glossary 是正式 terminology SSOT;reference Markdown 保持 maintainer/reference 性質。


12. Translation authoring pipeline

M02-D / E / F 有大量翻譯工作,不能只定 schema 與 CI,必須定義產出與 review 流程。

12.1 Draft 產出方式

允許使用外部 AI session 批次產生 translation draft,因為本專案本來就允許開發/維護時使用外部 AI 工具。

但:

可人工翻譯、AI-assisted、或兩者混用;最後都必須經相同 lint / review / evidence gate。

12.2 Batch 粒度

大量資料依 category / coherent dataset 分批 author、review、commit,例如:

spells
features
conditions
equipment
backgrounds
...

每批 commit 應保持 dataset schema-valid,並盡量讓該 batch 的 required fields 完整。

分批 commit 不代表可以分批關閉 Subphase。

M02-D complete scope all green → 才能 close D
M02-E complete scope all green → 才能 close E
M02-F complete scope all green → 才能 close F

不得翻一半 D 就宣告 D closeout 並跳 F,之後再回來補。

12.3 Commit 前自動檢查

每批至少跑:

自動 lint 不取代人工規則語意 review。

12.4 Human review 最低要求

Glossary / canonical terminology:新增或變更的正式 glossary entry 必須 100% review。

Long-form translation batch:每個 category 至少人工抽審:

max(10 entries, 10% of that batch)

若 batch 小於等於 10 筆則全審。

抽審優先包含玩法理解敏感內容:

若抽審發現系統性翻譯問題,不能只修抽到的幾筆;必須擴大 review / 修正同類 batch。

12.5 Batch evidence

每批至少留下可追溯 evidence:

category / pack
entry count
required field count
translation source/method(human / AI-assisted / mixed)
human-reviewed entry count
glossary lint result
schema/completeness result
known exceptions(若有,且不能是 required missing translation)

Evidence 可以放在 commit / closeout artifact / machine-readable report;不要求每批建立新永久 Markdown 文件,但 M02-H 必須能彙整證據。


13. Completeness model

M02 建立可機器驗證的 translation coverage contract。

completeness 集合:

enabled content packs
× M02-C required localizable fields
× supported locales

M02 closeout enabled packs:

srd5.1
phb2014
scag
gos

對於 canonical content 中目前沒有 product surface 的 field,不為了數字 100% 強行翻譯;但是否 required 必須由 localizable field policy 決定,不可人工隨意忽略。

缺失報告至少列出:

另外必須檢查:


14. CC BY 4.0 adaptation attribution

SRD 5.1 的 zh-TW translation 是對 CC BY 4.0 material 的修改/改作。

M02-H closeout 時必須更新 data/srd5.1/NOTICE.md,明確說明本專案提供 SRD 5.1 實際被翻譯之 user-visible presentation text 的繁體中文翻譯,並標示該內容已被修改/翻譯。

NOTICE wording 必須與實際 scope 一致;若 M02 只翻目前 user-visible fields,不得寫成「完整翻譯整份 SRD 5.1」。


15. M02 Subphase 順序

三份 M02 文件固定:

M02-A — Locale Foundation & Runtime Switch
M02-B — Full UI Copy Localization
M02-C — Localized Content Model & Terminology Contract
M02-D — SRD 5.1 Names & Structured Text
M02-E — SRD 5.1 User-Visible Descriptions
M02-F — PHB / SCAG / GoS Localization
M02-G — Localized Search, Errors & Completeness Gates
M02-H — Full M02 Integration & Closeout

M02-A — Locale Foundation & Runtime Switch

實作契約

不做


M02-B — Full UI Copy Localization

實作契約

將目前既有 product surface 的 static UI copy 移到 localization resources:

UI component 不再新增直接 user-visible hardcoded English / Chinese 文案,必要 exceptions 必須是 product name / technical token。

Translation resource key 應以語意/功能命名,不依完整英文句子本身當 key。


M02-C — Localized Content Model & Terminology Contract

實作契約

C closeout 時不要求 SRD 全資料已翻完,但 foundation 必須用 fixture 證明同一 StableKey / field 可正確呈現兩語,並能判定 required vs not-yet-user-visible field。


M02-D — SRD 5.1 Names & Structured Text

實作契約

依 M02-C policy 完成 SRD 5.1 目前 user-visible 的 names / labels / structured short text zh-TW / en coverage。

典型包含:

這是範例,不是另一份 scope SSOT;實際 required field 永遠以 policy 為準。

不得改 StableKey 或 canonical mechanics refs。


M02-E — SRD 5.1 User-Visible Descriptions

實作契約

依 M02-C policy 完成目前 product surface 已顯示的 SRD 5.1 long-form / explanatory text 雙語 coverage。

不得因 canonical dataset 有 description 就自動把所有 description 列為 M02 required;例如尚未被任何畫面顯示的 magic item full description 可延後到首次 expose 的 Subphase。

翻譯需維持規則語意、數值、骰式、條件與限制,不得因翻譯改變 rules meaning。

長文可以使用 paragraph / list 等結構化 presentation,但 canonical mechanics 不依翻譯文字解析。


M02-F — PHB / SCAG / GoS Localization

實作契約

M02 closeout 前已正式 runtime 化的 non-SRD packs:

phb2014
scag
gos

依 M02-C policy 完成所有目前 user-visible content 的 zh-TW / en presentation coverage。

docs/暫用規則資訊/ 對應 PHB / SCAG / GoS 文件作 zh-TW draft / terminology priority input;正式 runtime presentation 仍進 localization resources,不 runtime parse Markdown。

至少覆蓋目前可見的:

Roleplay suggestion reuse 必須 reuse identity / source relationship,而不是把另一語言 raw sentence 當 mechanics inheritance。


M02-G — Localized Search, Errors & Completeness Gates

實作契約

此 Subphase 後,新增/修改/首次 expose 正式 user-visible content 若缺任一 supported locale,測試應能失敗。


M02-H — Full M02 Integration & Closeout

實作契約

進行完整 integration hardening:

Documentation closeout 必須同步:

M02 closeout 後新增全專案永久要求:

任何後續 Subphase 新增、修改,或因新畫面而首次 expose user-visible system / rules content,都必須同步維護所有正式 supported locales;缺任一語言即視為該 Subphase 未完成。

M02 closeout 後:

Resume M01-D — VGM Race Expansion

M01-D~M01-I 的新增 content / UI 必須在各自 Subphase 同步交付 zh-TW / en presentation。