From fb46da29cf1a18ff227f6316e4f1c3219b9f7e9b Mon Sep 17 00:00:00 2001 From: ETWen Date: Tue, 20 Oct 2026 09:50:03 +0800 Subject: [PATCH] docs: document i18n conventions and Phase 17 (v0.8.0) Co-Authored-By: Claude Opus 5.5 --- ARCHITECTURE.md | 32 +++++++++++++++++++++++++++++++- CLAUDE.md | 20 +++++++++++++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index fcb14b8..78a62f4 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -100,8 +100,12 @@ STPViewer/ ├── STPViewer.csproj # net8.0-windows, UseWPF ├── App.xaml / App.xaml.cs # 全域例外處理(log + 訊息框存活;%LOCALAPPDATA%\STPViewer\error.log) ├── MainWindow.xaml / .cs # 版面 + 滑鼠拾取事件 + ├── i18n/ # 語言包 en / zh_tw / zh_cn.json(輸出到 exe 旁;啟動時掃描,免重編) + ├── Localization/ + │ └── LocExtension.cs # XAML {loc:Loc Key} → 綁定 LocalizationService[Key](切語言即時更新) │ ├── Models/ + │ ├── LanguageDefinition.cs # 一個語言包(Id = 檔名、Key = 顯示名、Data = 翻譯表) │ ├── FaceInfo.cs # GeometryModel3D ↔ B-rep Face 對照(STL 為 null) │ ├── MeasureMode.cs # enum: None/Point/Distance/Edge/Face/Circle/Angle/FaceDistance/Align/Align3/Drag/Interference/Volume │ ├── MeasurementResult.cs # 量測結果(雙單位 lambda、3D 標籤同步) @@ -112,6 +116,8 @@ STPViewer/ │ ├── Services/ │ ├── StepImportService.cs # STEP/STL/DXF 讀檔 + 三角化 + 裝配樹 + │ ├── StlMeshReader.cs # STL 直接解析(binary/ASCII,不經 CADability;v0.7.1) + │ ├── LocalizationService.cs # 語言包載入、目前語言、[key] 查詢(缺字回退英文)、LanguageChanged │ ├── MeasurementService.cs # 點/線/面/圓/角度/面距/體積質心 幾何計算(吸附含圓心) │ ├── InterferenceService.cs # 干涉檢查:三角形-三角形相交(區間法)+均勻網格加速;無干涉時近似最小間隙 │ ├── RigidAlign.cs # 三點對齊/旋轉的剛體變換數學(Matrix3D列向量 ↔ ModOp行向量 轉換) @@ -126,6 +132,8 @@ STPViewer/ ├── MainViewModel.Section.cs # 剖面(v0.4.0 起背景平行裁切) ├── MainViewModel.Interference.cs # 干涉檢查指令 ├── MainViewModel.Export.cs # CSV / 截圖 / STEP / STL 匯出 + ├── MainViewModel.Localization.cs # 語言切換指令 + 切換後刷新量測/樹/狀態列文字 + ├── QuickBarViewModel.cs # 快速列按鈕註冊表(key/文字 key/預設值) ├── StlExportViewModel.cs # STL 匯出對話框 VM(選項 + 即時摘要) └── ModelNodeViewModel.cs # 裝配樹節點(可見性/顏色 cascade) ``` @@ -201,7 +209,8 @@ class MeasurementResult | 快速鍵 | P 點 / D 距離 / E 邊 / F 面 / C 圓 / A 角度 / M 面距;同鍵再按=退出;Esc=取消進行中量測→退出模式 | | | 樹操作 | 搜尋框過濾節點名稱;右鍵:只顯示此節點 / 反轉顯示 / 全部顯示 / 量體積質心 | tooltip 含外形尺寸 L×W×H | | 體積/質心 | 樹節點右鍵「⚖ 量體積/質心」 | signed volume(封閉實體)+ 質心標記 + AABB 外形尺寸 | -| 設定/MRU | 自動記住視窗位置大小、單位;「▾」最近 10 個檔案 | %LOCALAPPDATA%\STPViewer\settings.json | +| 語言 | 視圖 → 語言 / 快速列下拉:English、繁體中文、简体中文(v0.8.0) | 即時切換(含既有量測文字)並記住;`i18n/*.json` 加檔即新增語言,缺字回退英文 | +| 設定/MRU | 自動記住視窗位置大小、單位、語言;「▾」最近 10 個檔案 | %LOCALAPPDATA%\STPViewer\settings.json | 支援格式:`.stp` / `.step`(B-rep + 裝配樹)、`.stl`(純網格,僅點/距離/角度/面距量測)、 `.dxf`(線架構檢視)。**IGES 不支援**(CADability 無 IGES reader)。 @@ -489,6 +498,27 @@ WPF retained-mode 每幀重走 visual tree → frame rate 崩。瀏覽模式因 --- +## Development Phases — 第九輪(多語系 v0.8.0) + +### Phase 17 — 執行期語言包 + 即時切換(工作量:L;外部貢獻 PR #1 by @CarmJos) + +**問題:** 介面字串全部寫死繁中,非中文使用者無法使用;新增語言要改程式重編。 + +- [x] **語言包**:`i18n/*.json`(`key` = 選單顯示名、`data` = key → 譯文)複製到 exe 旁; + 啟動時 `LocalizationService` 掃描,檔名即語言 Id(`zh_cn.json` → `zh_cn`);壞檔/重複 Id 略過記 Trace +- [x] **查詢與回退**:`LocalizationService[key]` → 目前語言 → 英文 → key 本身;`Format` 格式錯誤時回退英文格式 +- [x] **XAML**:`{loc:Loc Key}`(`LocExtension` = 綁 `LocalizationService.Instance[Key]`,`Item[]` 變更即時刷新) +- [x] **程式內文字**:狀態列 `SetStatus(() => Get/Format(...))`、量測/樹節點文字延後產生, + `LanguageChanged` → `RefreshLocalizedText()` 重算(與 mm⇄inch 同一套延後產生模式) +- [x] **初始語言**:settings.json `Language`,null → 依系統 UI 語系(zh-Hant/TW/HK/MO → zh_tw,其他 zh → zh_cn) +- [x] 關於視窗版本紀錄改為 key(`Ui.About.ReleaseXYZ.Title/ChangeN`),三語各一份 +- [x] SmokeTest `--localization-test`:語系解析(zh-Hans/Hant/TW…)、缺字/格式錯回退英文、壞檔容錯、 + 內建語言包格式參數一致、VM 切語言後既有量測/3D 標籤/快速列即時更新 + +**驗收:** 三語切換即時生效(含已存在的量測結果與狀態列)、重開保留;刪掉某語言檔中的 key 時顯示英文不崩潰 + +--- + ## Future Extensions(下一輪) - **大檔重開快取** — 匯入成功後把三角網格 + 裝配樹序列化成 sidecar 快取檔(以來源檔 hash 驗證), diff --git a/CLAUDE.md b/CLAUDE.md index 0ab651a..99312c8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ CAD 3D 檢視器(Windows 桌面 WPF, .NET 8):STEP/STL/DXF 匯入、STEP 裝配樹(搜尋/隔離顯示)、 點/距離/邊/面/圓/角度/面距/體積質心量測(吸附含圓心)、兩點對齊(平移)、三點對齊(旋轉+平移)、 軸向旋轉 90°、拖曳模式、干涉檢查(≥2 檔兩兩配對)、剖面(X/Y/Z + 3點任意平面)、 -標準視圖+正交投影、量測快速鍵+Esc、mm⇄inch、CSV/截圖/STEP/STL 匯出(STL 有參數對話框)、設定與 MRU 保存。 +標準視圖+正交投影、量測快速鍵+Esc、mm⇄inch、多語系(英/繁/簡,執行期語言包)、CSV/截圖/STEP/STL 匯出(STL 有參數對話框)、設定與 MRU 保存。 詳細設計見 [ARCHITECTURE.md](ARCHITECTURE.md)。 ## 技術棧 @@ -49,8 +49,8 @@ dotnet publish src/STPViewer -c Release -o publish/STPViewer (樹搜尋框、剖面數值框要能打字),新增輸入控件不用再各自處理 - UI 三層(v0.7.0):**選單列**(全部功能,分類下拉)+ **快速列**(`QuickBarViewModel` 註冊表, 使用者勾選常用按鈕,XAML 索引子綁定 `QuickBar[Key].IsChecked` 控 Visibility,按鈕本體維持靜態綁定)+ - **剖面參數列**(只在 SectionEnabled 顯示)。新增功能要三處都接:選單分類、快速列註冊表 - (含預設值)+ 對應 XAML 按鈕;勾選清單存 settings.json `QuickBarKeys`(null = 預設) + **剖面參數列**(只在 SectionEnabled 顯示)。新增功能要四處都接:選單分類、快速列註冊表 + (含預設值)+ 對應 XAML 按鈕、**三個語言包的文字 key**;勾選清單存 settings.json `QuickBarKeys`(null = 預設) - 使用者設定 `SettingsService`(%LOCALAPPDATA%\STPViewer\settings.json):視窗(MainWindow 管)+ 單位/MRU(VM `LoadSettings`/`SaveSettingsInto`);壞檔回預設、儲存失敗靜默 - 匯出 STEP 走 `CADability.ExportStep.WriteToFile(file, Project.CreateSimpleProject()+Model.Add)`; @@ -65,6 +65,13 @@ dotnet publish src/STPViewer -c Release -o publish/STPViewer OnViewportClick 最前面攔點擊);換軸/關剖面/Esc 會重置。平面位置一律用「AABB 8 角投影到法向」內插, 軸向與任意法向共用同一段程式,不要改回逐軸特化 - 量測文字一律 `Func` 延後產生(mm⇄inch 即時切換);內部數值永遠存 mm +- 🌐 **多語系(v0.8.0,PR #1 by @CarmJos)**:介面文字**一律走 key,不可寫死字串**。語言包 `src/STPViewer/i18n/{en,zh_tw,zh_cn}.json` + (`key` = 選單顯示名、`data` = key → 譯文;建置時複製到 exe 旁,啟動掃描,加檔即新增語言免重編)。 + XAML 用 `{loc:Loc Ui.Xxx}`;程式用 `LocalizationService.Get(key)` / `Format(key, args)`; + 狀態列用 `SetStatus(() => Get(...))`(延後產生,切語言時 `RefreshLocalizedText()` 重算 — 直接設 `StatusText` 切語言不會更新)。 + 新增文字 key **三個 json 都要加**(`en.json` 是 key 清單正本;缺字執行期回退英文、再缺顯示 key 本身)。 + key 命名:`Ui.Main.*`(主視窗)/ `Ui.StlExport.*` / `Ui.About.*` / `QuickBar.*` / `Runtime.*`(狀態列訊息)/ `App.*`。 + 選用語言存 settings.json `Language`(null = 依系統 UI 語系)。**程式碼註解維持中文**(設計理由與「不要改回 X」都寫在註解,勿精簡掉) - 裝配樹節點(`ModelNodeViewModel`)的可見性/邊線/顏色向下 cascade - 剖面只換 `GeometryModel3D.Geometry`(`FaceInfo.Mesh` 保留原始 frozen mesh 供還原與量測) - ⚡ 剖面裁切是**背景平行**(v0.4.0):`ApplySection` 在 UI 快照 (model, frozen mesh) → `Task.Run`+`Parallel.For` @@ -98,7 +105,8 @@ dotnet publish src/STPViewer -c Release -o publish/STPViewer - 干涉/面距/對齊等運算在背景執行緒;`Freeze()` 幾何後才跨執行緒 - 匯入在背景執行緒;`Freeze()` 幾何後才跨執行緒 - 發新版:升 csproj `` 之外,記得在 `AboutDialog.xaml.cs` 的 `Changelog` 陣列**頂端**加一筆 - (口吻寫給一般使用者:「你會感覺到什麼」,不是技術 changelog)。 + (口吻寫給一般使用者:「你會感覺到什麼」,不是技術 changelog)。v0.8.0 起內容是 key + (`Ui.About.ReleaseXYZ.Title` / `.ChangeN`),**三個語言包都要寫**。 ⚠️ WPF **頂層 MenuItem 直接掛 Click 不會觸發**(實測滑鼠/鍵盤都沒反應),要開視窗的入口一律放子選單(如 說明 → 關於) - Commit 格式:Conventional Commits(`feat:` / `fix:` / `docs:` …) @@ -133,7 +141,9 @@ dotnet publish src/STPViewer -c Release -o publish/STPViewer `--align-test`(三點對齊剛體變換 + ModOp↔Matrix3D 一致性)、`--make-dxf`(產測試檔)、 `--export-test `(STEP 匯出往返:寫出→回讀比對實體數)、 `--stl-export-test [file.stp]`(STL binary/ASCII 往返 + 退化濾除;給 stp 加測 B-rep 精細重算)、 - `--make-stl [triCount]`(產測試用 binary STL,預設 150 萬三角形,量 STL 匯入效能用) + `--make-stl [triCount]`(產測試用 binary STL,預設 150 萬三角形,量 STL 匯入效能用)、 + `--localization-test`(語言包載入/回退/壞檔容錯 + VM 即時切換;改 i18n 或加文字要跑) +- Linux 也能編 Windows 版:`~/.dotnet/dotnet build/publish ... -p:EnableWindowsTargeting=true`(SmokeTest 是 net8.0-windows,只能在 Windows 跑) - **絕不要用 PowerShell regex/Set-Content 改 .cs 檔** — Windows PowerShell 5.1 預設編碼會把 UTF-8 中文弄成亂碼(已踩過,靠反編譯 DLL 救回)。文字取代一律用 Edit 工具 ## For_AI/