多語言網站搬遷最容易搬丟的東西
不是內容,是「哪一頁對應哪一頁」。通用爬蟲眼裡 /ch/news/x 和 /en/news/x 就是兩個不相干的網頁——這層關係一旦搬丟,新站的語言切換按鈕就是壞的。
動手之前,先花五分鐘量你的舊站到底有沒有 hreflang。幾乎每份教學都說「先讀 hreflang,那是最權威的訊號」——理論正確,但真實的舊站常常一則都沒有(我量過的那個站:528 頁、0 則)。押在它上面之前先確認它存在。
配對訊號的優先序是:明確的內容 ID → hreflang → URL 結構對稱 → 共同 metadata → 語意相似度,逐級往下退。配不到的誠實列出來,不要為了配對率放寬規則——配錯比漏配更傷,因為你看不見。
先說明利益關係:§ 07 提到的 Cornhsu.PolyMigrate 是我做的——MIT 授權、免費、我沒有從中獲得任何收入,那一節已標示並寫出它的限制。文中的量測數字也出自它的實際案例——包含一個對它自己不利的結論:hreflang 是最權威的訊號,但因為沒有素材可以驗證,它刻意只拿來「建議」而不直接配對。
這篇會回答
- 為什麼「跨語言對應」會在搬遷中消失
- 五種配對訊號,以及它們的優先序
- 為什麼「先看 hreflang」在真實舊站上常常撲空
- 配不到的時候該怎麼辦
- 現成工具的狀況
搬丟的是關係,不是內容
搬站工具很多,抓 HTML、轉 Markdown、下載圖片、改連結——這些都有成熟方案。但多語言站有一個額外的東西要搬,而且幾乎所有通用工具都不管它:
「這一頁是那一頁的翻譯」這件事本身。
舊站上這個關係可能藏在資料庫的某個欄位、藏在語言切換按鈕的連結裡、或只是靠 URL 長得像。搬到新站之後,如果沒有人把它記下來,你會得到一堆各自獨立的頁面——內容一頁不少,但語言切換按鈕不知道該切到哪裡去。
更麻煩的是這個錯誤不會報錯。網站建得起來、每頁都打得開、SEO 檢查也不會叫。你只會在某天發現英文版的「關於我們」切過去變成中文首頁。
配錯比漏配更傷——漏配你看得見,配錯你看不見。所以這件事的正確目標不是「配對率越高越好」,而是「配得起來的自動配,配不起來的誠實列出來」。一份寫著「這 49 組我配不出來」的清單,比一份看起來全配好、但裡面混了幾組錯配的結果有用得多。
五種配對訊號
依可靠度排序。實務上是逐級往下退,不是選一個用。
舊系統的內容 ID
舊 CMS 如果有 translation group ID、共用 GUID,或任何一個明確表達「這幾筆是同一則內容」的欄位——用它,別想別的。這是唯一不需要推測的訊號。可惜多半只存在於資料庫裡,光靠爬 HTML 拿不到。
hreflang / rel="alternate"
頁面 <head> 裡的 <link rel="alternate" hreflang="en" href="...">,或 sitemap 裡的 xhtml:link。這是標準做法、語意明確,理論上是爬 HTML 能拿到的最權威訊號。下一節會講為什麼實務上常常撲空。
URL 結構對稱
/zh-tw/products/widget ↔ /en/products/widget——把語言前綴拿掉之後路徑相同。這是實務上命中率最高的一條,因為多數 CMS 是這樣產 URL 的。做法是正規化掉語言段落再比對剩下的路徑。
共同 metadata
相同的 canonical ID、產品 SKU、下載檔案 ID、共用的相簿或圖片、發佈日期加作者。適合電商與有結構化資料的站——SKU 通常比任何 URL 演算法都準。
文字相似度 / 語意比對
標題、內文做跨語言 embedding 比對,產出候選與信心分數。這是前面全部落空時的最後手段,只能拿來產生「建議」,不能直接當結論——必須有人覆核。
有一條路千萬不要走
不要用 URL 字串相似度來配語言版本。 /products/、/produkte/、/產品/ 的字串相似度接近零,但它們是同一頁;反過來 /news/2025-summer 與 /news/2025-winter 相似度很高,卻是不同的兩篇。這條路看起來很聰明,實際上是錯配的主要來源。
為什麼「先看 hreflang」常常撲空
幾乎每一份談這件事的資料都會說:先讀 hreflang,那是最權威的訊號。這個建議在理論上完全正確。
但我在一個真實的搬遷案例上量過。對象是一個 2000 年代的 PHP 機構網站,中英雙語——正是這類工具的典型客戶:
| 檢查項 | 結果 |
|---|---|
鏡像下來的 .html 檔數 | 528 |
含 hreflang 的頁面 | 0 |
含 rel="alternate" 的頁面 | 0 |
| 鏡像裡的 sitemap | 無 |
原站 /sitemap.xml | 404 |
你可以拿這幾行去量你自己的站:
R=/path/to/crawl/raw grep -rli "hreflang" "$R" | wc -l grep -rli "rel=[\"']*alternate" "$R" | wc -l find "$R" -iname "*sitemap*"
n=1,所以這個 0 不證明「舊站都沒有 hreflang」。但它指出一個結構性的問題,而這個問題比單一樣本更值得注意:
hreflang 維護得好的站,正好是最不需要搬遷工具的站
會把 hreflang 標對的網站,背後通常有一個稱職的 SEO 或開發團隊。而那樣的團隊,多半也有能力自己處理搬遷。這兩個屬性是反相關的。
更進一步:hreflang 正確而且路徑對稱的站,訊號 3(URL 對稱)本來就配得起來,hreflang 加零。所以 hreflang 真正能派上用場的,是「宣告正確 且 路徑不對稱」那條窄帶——而這條帶子有多寬,我沒有資料可以回答。
結論不是「不要讀 hreflang」,而是:讀,但不要把整個方案押在它上面。也不要在還沒量過你的舊站之前,就假設它會是主力訊號。
就算讀到了,也還有五道門要過
hreflang 有宣告,不等於那則宣告可以用來配對。至少這五種情況要先擋掉:
x-default——它不是某個語言版本,是「都不符合時去哪」。- 自我指涉——指向自己。這是標準做法,但配對上零資訊。
- 站級頁面——語言選擇頁那種,它不是誰的翻譯。
- 目標不在鏡像裡——宣告指向一個你根本沒抓下來的網址。
- 目標歧義——多個來源的 alternate 指向同一個目標。
最後那個是最陰險的。我是實際跑一個對抗性的假站才發現要加:如果整站的 alternate 因為模板複製而全部指向首頁,少了這道門,工具會產出「英文首頁 = 某篇中文新聞」這種建議——而且還掛著 hreflang 這個最權威的證據標籤,反而比沒有證據更容易被相信。
配不到的時候
五種訊號全部落空的頁面一定會有。同一次量測裡,那個站有 50 個只有單語的 key,三個既有啟發式合計建議 0 筆。
逐一看過之後,狀況是這樣:
- 有些是真的可以自動救的。「光明燈法會」的中英兩頁只差一個分隔符——
2025-light-offering對2025_light_offering,三個啟發式全部落空。加一條 slug 正規化(連字號、底線、大小寫)就配上了。這種是規則沒寫全,不是問題無解。 - 有些是預設錯了。原本假設中英兩頁會共用同一個相簿,實測是各自引用自己語言目錄下的圖——即使是同一張圖的兩份拷貝(
2026_gmd.jpg與2026gmd.jpg),工具眼中就是兩張不同的圖,一組都配不出來。假設要用真實資料驗證。 - 剩下的多半真的無解。要嘛只有單語版本,要嘛需要真的看得懂兩種語言才配得起來——
2026_emperor_liang_amitabha與2026_lianghuang_sanshi_xinian這種,沒有安全的自動規則配得到。
對最後這一類,誠實列進缺漏清單就是正確行為。不要為了讓數字好看而放寬規則——放寬規則換來的配對率,代價是你不知道哪幾組是錯的。
實務上該產出的東西是一份可覆核的對照表,每一列都帶著「憑什麼這樣配」的證據欄,讓人可以只檢查低信心的那些:
key lang old_url source confidence
2025_light_offering zh-Hant /ch/news/2025_light... slug_normalized 0.86
2025_light_offering en /en/news/2025-light... slug_normalized 0.86
about zh-Hant /ch/about.php symmetric_path 1.00
about en /en/about.php symmetric_path 1.00
2026_emperor_liang zh-Hant /ch/news/2026_lianghu... missing —
現成工具的狀況
老實說:沒有一個裝了就能自動配好任意多語舊站的工具。這件事高度依賴舊站的結構,而舊站的結構千奇百怪。目前的選項大致分三類:
目標端是特定 CMS
如果新站要落在 Umbraco、Sitecore、Optimizely、Orchard Core 這類本身就有「同一內容的多個語言版本」模型的系統上,它們的搬遷工具會把語言關係一起帶過去——前提是來源端也要有那個關係。Proxima Content Migration(Epinova)是這條路上最成熟的一個,明確支援多語言內容與舊新 URL 對照,自動配不到時會產出 TODO;但目標端必須是 Optimizely。
SEO 工具產對照表
Screaming Frog 爬完可以匯出 hreflang 報表,直接得到語言配對矩陣。前提一樣是舊站真的有 hreflang(見 § 03)。它是 Java 桌面程式,不是可以塞進 pipeline 的函式庫。
自己組
.NET 的零件都在:HttpClient 或 Abot 爬站、AngleSharp 或 HtmlAgilityPack 解析、FuzzySharp 或 F23.StringSimilarity 做相似度、ML.NET 做 embedding、Microsoft.AspNetCore.Rewrite 套用結果。多數團隊走這條路。
要提醒的是:ASP.NET Core 的 localization 不是這件事。 IStringLocalizer、.resx、request culture 解決的是「執行中的應用程式怎麼顯示多語言」,不是「怎麼把舊站的跨語言關係搬過來」。同理,.NET Upgrade Assistant 是升級專案框架的,跟網站內容搬遷無關。
我做的那一個
以下是我自己的工具,請自行打折。上面那些量測數字都出自它的實際案例。
Cornhsu.PolyMigrate 是一個 dotnet tool(也可以 npx 執行),把舊的動態網站搬成靜態站的 Markdown,多語言配對是核心功能而不是外掛。
它對 § 02 那五種訊號的處理是:hreflang 全部記錄下來——包含不可用的宣告與被擋下的原因,輸出成 hreflang_map.csv;接著走路徑對稱、共用相簿、slug 日期正規化、標題相似度逐級往下退。但 hreflang 只用來「建議」,不直接改寫配對結果。
這個選擇是刻意的,理由就是 § 03 那張表:唯一能拿來驗收的真實站,hreflang 是 0 則。把最權威的訊號提升成「直接覆寫」是整條路上錯了最貴的一階——配錯的 key 會流進 frontmatter、轉址對照表、和你自己的匯入程式,而且不會有任何一個地方報錯。沒有素材可以驗收的功能,我選擇不做。
語言不限兩種,lang_map 宣告幾組就支援幾語,輸出一律 BCP-47。配不到的一律列進缺漏清單。
你該知道的限制:單人維護;hreflang 目前只到「建議」層級,不做權威覆寫;沒有圖形介面;它是為「搬成靜態站 Markdown」設計的,如果你的目標端是某個 CMS,前面提到的 CMS 原生方案會更直接。
MIT 授權開源。以一個真實的中英雙語舊 PHP 站完整驗證——516 頁、4.6GB 媒體、231 篇雙語自動配對、找回 13 篇被原站移除索引的孤兒文章、修正 141 張 EXIF 方向顛倒的照片、全站巡檢 0 錯誤。verify 的 exit code 可直接進 CI。
一句話總結
多語言搬遷真正的工作不是搬內容,是搬關係。訊號有五種,優先序是「明確 ID → hreflang → URL 對稱 → 共同 metadata → 語意相似」,逐級往下退。但在動手之前,先花五分鐘量一下你的舊站到底有沒有 hreflang——很多人照著教學把方案押在它上面,然後才發現那個站一則都沒有。配不到的誠實列出來,別為了配對率放寬規則。
寫於 2026-08-18。文中的量測數字來自單一真實案例(n=1),只能說明「這類站可能長這樣」,不能推論全體。請以你自己的量測為準。