Boloop 閱讀示意图(AI 生成):語言切換需要保持 URL、正文與控件狀態的一致性。

這次語言切換故障的現象非常簡單:從英文切換到簡體成功後,再選擇繁體,雖然下拉選單顯示的是繁體,但 URL、標題和正文卻仍然停留在簡體版本。

如果只檢查下拉選單的值,這個操作看起來已經成功了。然而,真正暴露問題的是幾個本來應該同步變化的地方,它們給出了不同的答案。

這是 Boloop 在 2026 年 10 月 12 日的早期私有預覽中記錄到的現象。它提醒我們,服務器端頁面已經顯示出來,與前端交互已經準備好,這是兩件需要分別處理的事情。

先將不一致的幾個狀態保留下來

當時的實際瀏覽器記錄來自已登錄的 Edge 会话。從英文切換到簡體可以完成,但在新顯示的頁面上立即選擇繁體時,控件值變了,其他內容沒有跟上。

還有幾個觀察結果同樣關鍵:頁腳的普通語言鏈接可以工作;刷新頁面或觸發主題更新後,顯示會恢復一致;稍後重試頁頭語言選擇,或者直接打開語言鏈接,也可以正常進入相應頁面。

這些現象使“這個語言完全沒有內容”和“所有語言路由都壞了”的說法不太符合觀察。但它們仍然不足以精確證明哪條腳本在什麼時刻失效。原故障沒有保留下完整的瀏覽器網絡追蹤,無法後來補寫一個確定的加載時間。

更合理的解釋是:原生選擇框在 React 安裝事件處理程序之前,已經接受了用戶輸入。它能改變自己的顯示值,但沒有完成應用所需的語言跳轉。我們把這個解釋作為有觀察支持的判斷,繼續用受控實驗檢查。

修復的是交互準備狀態

針對這段窗口,候選實現讓服務器端 HTML 中的語言控件保持禁用狀態,並標記為忙碌。React 的首次渲染保持相同狀態,掛載完成後再允許操作。

這樣,尚未準備好的控件不會表現成一個可以正常使用的入口。等待期間,用戶仍能通過頁腳的真實語言鏈接導航。這些鏈接不是 JavaScript 事件的裝飾外殼,而是保留了實際的 URL。

當前端準備好後,普通語言切換在同一頁面中更新 React 狀態和瀏覽器歷史,保留當前資源的深層路徑,並同步語言元數據。對於修改鍵點擊、無 JavaScript 和直接導航,普通鏈接仍可發揮作用。

這些改變共同解決了可見頁面與可用交互之間的銜接問題。它们並沒有要求改動託管站点的訪問範圍、認證規則或資源路徑。

另一個錯誤,應作為另一條原因處理

排查過程中還單獨複現了瀏覽器存儲拋出 SecurityError 的情況。原來的存儲讀取可能導致啟動中斷,寫入失敗也可能打斷語言導航。

因此,我們將本地存儲視為可選功能:讀取失敗時使用預設值,寫入失敗也不阻止用戶繼續操作。主題和語言的使用不應假設“這個瀏覽器一定允許寫存儲”。

但這並不是原來那次 Edge 故障已經確認的根因。兩種問題都需要修補,但證據不同。將它們合併為「因為 localStorage 出錯導致切換失敗」會丟失原始觀察,也讓後來的回歸測試不知道應該覆蓋什麼。

故意延緩加載,才能看見那段空隙

受控瀏覽器回歸給 JavaScript 響應增加了 15 秒延遲。這種延遲來自測試環境,用於擴大觀察窗口,不是對原來用戶網絡速度的測量,也沒有進入正式 Worker。

等待腳本時,服務端內容已經可讀,語言控件保持禁用;頁腳鏈接仍可打開另一種語言。腳本完成後,控件啟用,再連續切換英文、簡體、繁體,檢查的不只是選項,而是整組狀態:

| 檢查位置 | 需要保持一致的內容 | |---|---| | 地址欄 | 當前語言前綴與原資源路徑 | | 頁面正文 | 對應語言的標題與內容 | | 頁面元數據 | 頁面語言和標題 | | 控件 | 當前語言的選中狀態 | | 瀏覽器歷史 | 後退、前進後的語言與內容 |

在那輪獨立 Chromium 回歸測試中,連續九次語言選擇保持一致,深層 Skill、軟件和文章頁面也覆蓋了切換、後退、前進與刷新。構建和相關自動檢查通過,但這些仍是當時受控環境的證據,不能代替原私有託管預覽上的同條件複驗。

後來的控件可以變,但這條約束仍然保留

Boloop 後來將公開頁面的原生下拉選單替換為統一的自定義菜單。新的外觀解決了另一個問題:系統彈出的列表與網站主題不一致。語言控制仍然需要保留水合階段的禁用與忙碌行為。

因此,這次故障並不是一份“原生 select 都不可靠”的結論。它更適合變成一個長期檢查:頁面出現時,哪些操作已經可以安全執行,哪些還在等待客戶端接管?

如果你也遇到“控件變了,頁面沒變”的情況,可以先同時記錄地址、正文、元數據和控件狀態,再比較立即操作與稍後操作、直接鏈接與腳本導航。必要時在隔離預覽中延緩資源加載。

這些對照能將一個偶發的界面問題轉化為可解釋、可回歸的問題。至於最終原因,則應留給實際觀察來決定。