React Routeri18n除錯靜態網站

英文頁的下載連結為什麼壞掉?雙語路由與靜態檔案的分界

··閱讀約 5 分鐘

本站曾遇到一個很容易漏掉的問題:繁中文章的附件可用,換成英文頁,下載連結就被加上 /en/。檔案實際放在共用的 /downloads/evidence/,伺服器並沒有另一份英文附件。讀者看到的連結文字沒有問題,真正錯的是路由層把檔案當成要切換語言的頁面。

這篇以 1a6b177 版的修正為例。你需要能開啟瀏覽器開發工具,並知道網站有原始檔、建置產物與部署三個階段。要完成的不是讓 HTTP 狀態變成 200,而是讓中英文讀者取得同一個正確檔案,且 HTML 小工具仍能直接開啟使用。

先分類目的地,再決定是否加語言前綴

目的地英文頁應使用行為
一般文章/en/article/react-chinese-ime-onchange前往英文文章
共用 ZIP/downloads/evidence/glb-measurements.zip保留共用路徑,提供下載
共用 Markdown/downloads/evidence/react-ime-2026-07.md保留共用路徑,提供下載
HTML 小工具/downloads/evidence/ime-event-logger.html保留共用路徑,在瀏覽器開啟
相同網站內,連結有不同語意

這裡有兩個獨立的決定:網址是否需要語言化,以及點擊後是否下載。共用 HTML 小工具不用加 /en/,卻也不該因為位於 downloads 目錄就一律強制下載。把兩個判斷合在「是不是附件」這個模糊名稱裡,很容易修好 ZIP 後又弄壞工具。

原生 a 標籤也可能拿到錯誤網址

本站的 LocalizedLink 會把站內路徑轉成對應語言。即使某些頁面切換會採用整頁載入,href 若已被改成 /en/downloads/...,依然是錯的。因此修正重點不只是「讓瀏覽器重新載入」,還要讓共用檔案避開頁面路由的網址轉換。

tsx
// Reduced from the site's link-block handling.
const isDownload = href.endsWith('.zip') || href.endsWith('.md');
const isSharedFile = href.startsWith('/downloads/');

if (isSharedFile || href.endsWith('.zip')) {
  return <a href={href} download={isDownload}>{label}</a>;
}
return <LocalizedLink to={href}>{label}</LocalizedLink>;

這是本文檢查版本的實際規則縮寫,不是涵蓋所有 URL 的通用函式。它處理本站目前使用的 /downloads/ 共用檔案與 ZIP 連結。像 .zip?revision=2 的網址,不會通過 endsWith(".zip");若仍位於 /downloads/ 下,路徑可保持正確,但這個版本不會因此加上 download 屬性。擴充格式前,要先列出你真的支援哪些網址。

若你的需求包含 query、大小寫副檔名或其他格式,可先用 URL 解析出 pathname,再做副檔名判斷;同時保留原始 href,避免丟掉 query 與 hash。跨網域連結也必須獨立考慮:download 屬性不是任意遠端檔案都會遵守的命令,實際行為還受同源限制、回應標頭與瀏覽器設定影響。

有預渲染的網站,要檢查兩份連結

本站有 React 文章頁,也有建置時產生 HTML 的文章渲染器。只修 React,使用者進站前拿到的 HTML 仍可能含錯誤 href;只修 HTML,瀏覽器啟動後又可能被 React 換回錯誤網址。這次修正必須在兩邊都保留共用檔案的路徑,並維持相同的下載判斷。

檢查時先看 View Source 或直接取得 HTML 中的 href,再看頁面載入完成後 Elements 裡的 href。若兩者不同,先處理渲染器不一致,再談快取。接著從英文文章實際點擊,確認目的地是 /downloads/...,而不是只在地址列直接貼上正確檔案網址。直接貼網址成功,無法證明文章上的連結正確。

開啟本文案例的輸入事件記錄器(HTML)下載本文案例的 IME 驗證紀錄(Markdown)

200 OK 還不夠:確認拿到的確實是檔案

SPA 主機可能把不存在的路徑回退到首頁 HTML。如果你只檢查狀態碼,錯誤附件也可能顯示成功。應再看 Content-Type 與內容:ZIP 不該以 <!doctype html> 開頭,Markdown 不該變成整個網站的導覽頁。對已知檔案,可比較部署檔與本地原檔的 SHA-256。

bash
curl --fail --location \
  https://keeponfirst.com/downloads/evidence/glb-measurements.zip \
  --output /tmp/glb-measurements.zip
file /tmp/glb-measurements.zip
unzip -t /tmp/glb-measurements.zip
shasum -a 256 public/downloads/evidence/glb-measurements.zip /tmp/glb-measurements.zip

最後一行要在包含該原檔的專案目錄執行;兩個摘要相同,才代表這次下載與本地檔案逐位元一致。若你沒有本地副本,可以先檢查 ZIP 能否解開、檔名與 README 是否符合文章描述。別把雜湊相同解讀成範例中的所有技術結論都已被證明,它只回答檔案一致性。

一份能實際驗收的最小矩陣

情境應檢查的結果
繁中與英文文章各點一次 ZIP網址皆為共用路徑;內容可解壓
點擊 Markdown取得文字檔;不出現 SPA 首頁
點擊 HTML 工具工具可操作;不被強制下載
比較初始 HTML 與載入後 DOMhref 和 download 語意一致
輸入一個不存在的附件路徑辨認 404 或 fallback;不要誤判成功
加入 query 的附件網址另列預期,不能沿用純副檔名假設
每次改連結分類後,重走這些情境

這類問題不需要先重寫整個路由系統。先把頁面與共用檔案的責任切清楚,修正兩份輸出,再從讀者會走的入口驗證。當下載檔本身就是文章的證據或範例,能否正確取得它,也是內容是否完整的一部分。

參考資料