開發紀錄
沒有翻譯,就不應該生成一個假的語言頁
從固定頁和筆記文章的不同路由規則,說明多語網站如何保留空狀態、只連到實際翻譯,並避免用假頁面填補語言缺口。
- 多語內容
- Astro
- 翻譯
- 內容工程
多語網站最容易被忽略的不是「有沒有翻譯」,而是「沒有翻譯時,網站要不要假裝有」。
固定頁通常可以在建置時準備好繁中、英文和日文版本;文章卻可能只有繁中草稿,或只有一篇正式中文稿。兩者如果使用同一套「看到語言清單就全部生成」的規則,網站就會產生一個網址存在、內容卻不存在的假頁面。
目前這個網站選擇另一條路:固定頁可以有完整的多語入口,筆記文章只有在實際翻譯檔案和發布狀態都成立時,才產生對應的文章頁。主要判斷是:空的語言入口可以誠實存在,假的翻譯文章不應該被生成。
固定頁和筆記文章的資料來源不同
首頁、關於、作品、合作、產品和筆記列表屬於網站固定頁。它們的語言集合是網站設定的一部分,英文和日文的固定頁在建置時就有對應的 route props 和翻譯文案。
筆記文章則來自 Content Collection。每份 Markdown 文章都有自己的 locale、stableId、slug 和發布狀態。文章路由不是對著語言清單盲目展開,而是先取得目前符合正式條件的文章,再依文章資料產生路徑。
可以把它想成兩條不同的資料流:
固定頁:語言集合 → 固定路由 → 對應文案
文章:實際 Markdown → 發布過濾 → 實際文章路由
固定頁的語言集合描述「網站支援哪些介面語言」;文章資料描述「哪一篇內容目前真的存在」。這兩個集合可能有不同數量,沒有矛盾。
stableId 用來找同一篇內容的翻譯
同一篇文章在不同語言之間可以共用 stableId,但每個語言仍然有自己的 slug、標題、摘要和正文。文章頁在建立語言切換連結時,會從目前正式文章集合中找出同一個 stableId 的其他語言版本。
這個查找方式有兩個限制,反而是它的好處:
- 沒有對應
stableId的檔案,就不會被當成翻譯。 - 即使檔案存在,只要還是草稿或發布日期尚未到,也不會出現在正式文章頁的翻譯連結裡。
因此,一篇繁中正式文章可以只有繁中網址;等英文稿也完成、通過校稿並取得發布資格後,英文網址才會加入同一組語言替代連結。
語言選單不應該把不存在的文章變成連結
固定頁的語言選單可以列出三種語言,因為三種固定頁都有對應路由。文章頁使用的 languageLinks 則來自實際翻譯集合;某個語言沒有文章時,選單顯示不可用狀態,而不是產生一個會回到首頁、顯示原文或返回 404 的假連結。
這個差異對讀者很直接:
- 有翻譯:提供可以前往的真實連結。
- 沒有翻譯:說明該語言版本目前不可用。
- 不把原文複製到另一個語言網址,冒充已翻譯內容。
- 不把讀者靜默導向另一種語言,讓他以為自己已經切換成功。
語言選單只是把資料狀態呈現出來,不負責替內容團隊補內容。
空狀態比假文章更誠實
目前英文和日文筆記列表沒有正式文章,但它們仍然有自己的 /en/notes 和 /ja/notes。列表頁會顯示空狀態,讓讀者知道這個語言入口存在,但內容尚未準備好。
如果為了讓畫面看起來完整,而把繁中文章複製到英文或日文列表,會出現幾個問題:
- URL 看起來像翻譯文章,但正文不是目標語言。
- 搜尋引擎可能收到多個不同網址、內容卻相同的頁面。
- 語言切換會讓讀者以為翻譯已經完成。
- 後續真正加入翻譯時,既有假頁的身份和連結會變得難以整理。
空狀態少了一點內容,卻把狀態說清楚。對內容網站來說,這比用一張看似完整的卡片掩蓋缺口更容易維護。
sitemap 也要遵守同一個邊界
假的翻譯頁不能只是不顯示在語言選單,還要從正式輸出的其他入口一起消失。文章的 sitemap 路徑使用正式發布文章集合產生,所以沒有翻譯的語言不會被加入文章 URL。
同樣的規則也適用於:
- 首頁最新文章區。
- 語言版本的筆記列表。
- 分頁路由。
- 文章頁的 canonical。
hreflang替代連結。- 相關文章和延伸閱讀。
只要其中一個入口把不存在的翻譯加回來,網站就會出現內容狀態不一致。翻譯是否存在,應該在內容資料入口先決定,而不是等每個頁面自己猜。
「有語言頁」和「有語言內容」不是同一件事
這個網站目前可以同時成立以下兩件事:
/en/about和/ja/about是可讀的固定頁。/en/notes/some-article和/ja/notes/some-article可能不存在。
前者代表網站介面提供英文和日文;後者代表某篇文章的翻譯供給還沒有成立。這不是不一致,而是兩種資料責任被分開了。
如果未來需要完整翻譯所有文章,可以逐篇新增相同 stableId 的語言檔案,再依每篇文章的校稿和發布狀態加入公開集合。網站不需要先替未來的翻譯建立空文章頁。
新增翻譯前可以檢查什麼
- 先確認這是現有文章的翻譯,不是另一篇共用相似標題的新文章。
- 保留相同的
stableId,為目標語言寫自然的slug、標題、摘要和正文。 - 確認目標語言檔案的
locale與所在目錄一致。 - 文章仍維持
draft: true,直到內容校稿和公開範圍確認完成。 - 驗證文章頁、語言選單、canonical、
hreflang和 sitemap 是否一起反映新狀態。 - 沒有翻譯時保留空狀態,不要先建立 placeholder 文章。
多語內容的完整度不應該由路由數量假裝出來。固定頁有三種語言,不代表每篇筆記也有三種語言;文章目前只有一種語言,也不代表網站的多語架構失敗。只要每個網址都誠實描述它實際提供的內容,讀者就不必猜測自己是不是看到了半成品。
紀錄範圍
本文整理目前固定頁、文章 Content Collection、語言切換、空狀態、canonical、hreflang 和 sitemap 之間的內容邊界。它沒有宣稱翻譯流程已經自動化,也沒有把目前的英文或日文空狀態寫成翻譯進度或讀者需求的量測結果。