Kanorio

雲端基礎設施

語系與在地化

在單一網站中支援多種語系,包含主要語系、無需額外點數的機器翻譯、語系感知傳遞與 SEO,並為託管與無頭前端提供相同的合約。

可用

網站擁有一個主要語系,並可新增更多語系。每個文字欄位皆保留其主要語系的數值;翻譯內容則儲存於旁邊的資料表中,每一筆記錄與語系各佔一行。新增語系時,系統會在背景翻譯整個網站,並於完成後發佈。託管網站與您建置的任何前端,皆透過相同的 locale 參數讀取相同的資料。

核心物件

  • 語系集 (Locale set)。 網站的語系包含一個主要語系、狀態(draft、translating、published、disabled)、每個次要語系的網址前綴(en、ja 或擁有者自選的前綴)以及自動翻譯開關。GET /api/v1/site 會在 locales[] 中列出這些資訊。
  • 翻譯 (Translations)。 每一筆記錄與語系各佔一行,包含草稿與已發佈的欄位資料、專屬的網址別名(單一區段)以及翻譯時來源記錄的 sourceHash。雜湊值用於偵測過時的翻譯,並防止外部工具覆寫較新的來源文字。
  • 可翻譯欄位 (Translatable fields)。 根據各內容類型架構衍生的註冊表,定義哪些路徑可進行翻譯:標題、RTF 文字、區塊文字、SEO 欄位、產品描述、長篇詳情、常見問題與購買備註、產品選項與變體描述、課程單元(包含文字課程與測驗問題,但不包含答案)、全站處理時間與購買備註、表單及法律頁面。集合欄位需透過 localized: true 啟用。價格、庫存、訂單、顧客與評論皆不進行翻譯。
  • 網址別名 (URL slugs)。 頁面、文章、分類、標籤、作者、產品、產品分類與集合項目,每個語系皆可擁有自己的別名。首次機器翻譯至某語系時,會從翻譯後的標題產生別名(拉丁語系語言會產生 ASCII 別名;其他語言若主要別名為 ASCII 則保留該別名),之後不會自動變更。頁面僅翻譯其自身的區段,因此某語系中的頁面路徑是根據該語系中各層級的別名所建構。固定的永久連結區段(如 /blog 與 /product)不會被翻譯。
  • 翻譯任務 (Translation jobs)。 新增語系或重試失敗批次時,會執行全站任務;後續對主要語系的編輯會以增量方式重新翻譯。任務與單筆記錄翻譯不消耗 AI 點數;每日呼叫上限會將工作排入隔日,而非直接失敗。

設定之間的關聯

語系、貨幣、商業市場與時區是四個獨立的設定。彼此互不依賴,因此網站可以使用英文撰寫、以歐元銷售,並採用東京時間運作。顧客的語系(Contact.locale)會在結帳、登入與提交表單時記錄,並決定其電子郵件、顧客帳戶與憑證的語系。

API 的運作方式

  • 使用 Content Delivery API 讀取。 每次讀取皆接受 locale(代碼或網址前綴)。未翻譯的欄位會回退至主要文字,回應內容會在 resolvedLocale 中說明服務語系,並在 availableLocales 中列出已翻譯的語系。透過別名讀取時,接受任何語系的別名並回傳該請求語系的 slug;頁面與產品會新增 localePaths(在每個線上語系中的路徑),集合項目則新增 localeSlugs。若網站不存在該語系,則回傳 400 UNSUPPORTED_LOCALE。/seo/*、/feed 與搜尋功能皆遵循相同的參數。請參閱 讀取內容。
  • 使用 Management API 管理。 localization.locales.* 可新增、更新、重新排序、移除及設定主要語系;localization.translations.* 可列出、讀取、寫入(使用 sourceHash 進行 upsert,以及設定或清除語系的網址別名)、發佈與刪除翻譯,並透過 translate 按需執行翻譯;localization.jobs.* 可讀取進度與重試。新增或移除語系會變更該語系的所有網址,並要求 confirm: true。語系代碼為自然鍵:新增已存在的語系會回傳 ALREADY_ADDED,移除不存在的語系會回傳 NOT_FOUND,因此重試呼叫不會建立第二個語系,且無需冪等鍵。
  • 監聽 Webhooks。 content.translation.published 與 deleted 會針對每筆記錄與語系觸發;localization.locale.published、unpublished 與 updated 則在語系集變更時觸發;localization.job.completed 與 failed 則針對全站任務觸發。每個內容事件上的 cacheTags 帶有 @<locale>,因此翻譯上線時僅會重新整理該語系。請參閱 Webhooks。
  • 在前端進行路由與標籤。 createKanorioMiddleware({ features: { locales: true } }) 會將主要語系的前綴重新導向至根目錄,提供 /<prefix>/llms.txt 與 /<prefix>/rss.xml,比對不含前綴的共享重新導向,並針對完整路徑比對語系重新導向(locale 設定)。requestLocaleOf、buildAlternates 與 languageSwitcher(傳入 localePaths)可讓您取得語系、標準網址 (canonical)、hreflang 以及與託管網站規則相同的語言選單。請參閱 Next.js 與 SDK 參考。
  • 顧客端文字。 Customer API 與 @kanorio/elements 接受 locale;若未提供,則使用顧客記錄的語系。課程與單元標題、訂單項目名稱與完成證書皆遵循此設定。請參閱 課程與成員。
  • 自動化電子郵件。 訂單、付款、運送、退款、登入與表單確認郵件會以顧客記錄的語系發送(若網站提供該語系),否則使用主要語系。若擁有者未自訂電子郵件,則使用內建措辭(每個網站語言皆有對應版本)。自訂電子郵件的翻譯方式與其他內容相同:其翻譯為 message_template 記錄類型(自訂範本的 ID),透過 localization.translations.* 針對各語系修正並於寫入時生效。在語系擁有自訂電子郵件的翻譯前,該郵件會以主要語系發送。範本變數(如訂單編號等三括號佔位符)必須與來源完全一致;新增變數的翻譯將被拒絕。
  • 匯出。 網站匯出內容包含主要語系內容旁邊的 localization/locales.json 與 localization/translations.json。

應遵循的行為

  • 主要語系於根目錄提供;其他所有語系皆位於其前綴之下。主要語系本身的代碼作為前綴時,會以 301 重新導向至根目錄。
  • 仍在翻譯中的語系對訪客或 Delivery API 而言不存在。當任務完成時,該語系會一次性發佈。
  • 移除已上線的語系會將其前綴重新導向至主要語系的頁面。其翻譯內容至少保留 30 天;重新新增該語系會重複使用這些翻譯,並僅翻譯缺失的部分。使用相同的前綴即可恢復舊網址。
  • 以回退方式提供的頁面(該語系尚未有翻譯)會取得主要語系的標準網址 (canonical) 且不含 hreflang,因此搜尋引擎不會索引重複內容。
  • 具有草稿與發佈生命週期的記錄(頁面、全域區塊、網站設定、文章與集合項目)會將編輯過的翻譯保留為草稿。發佈記錄會使每個語系的草稿上線;localization.translations.publish 可單獨發佈一個語系,並需要記錄的發佈權限(site:publish、blog:publish 或 collections:publish)。編輯翻譯不會將主要語系標記為已變更。
  • 使用其他語系別名的網址,或在語系已有專屬別名時使用主要別名,皆會重新導向至該語系的別名。變更已上線的別名會從該語系的舊網址新增 301;清除別名則會使該語系再次遵循主要別名。
  • 網站僅有一個語系時可變更主要語系。在多語系網站上變更主要語系會重寫所有網址,目前尚未開放此功能。
  • 相同的規則適用於託管網站與無頭 (headless) 前端;npx @kanorio/cli doctor 可檢查您的前端是否在每個語系前綴下提供翻譯後的標題、列出每個線上語系的 hreflang,並提供各語系的 llms.txt。

API 開放的範圍

  • Locale set & translations (add a locale, full-site machine translation, review)可用
    API
    Management API localization.locales.* (list, add, update, reorder, remove, set_primary), localization.translations.* (list, get, upsert with sourceHash, publish, delete, translate), localization.jobs.*; REST /sites/:id/locales, /sites/:id/translations
    託管網站
    /settings locale list (status, progress, URL prefix, auto-translate) and the editor's locale switcher for corrections
    Webhooks
    content.translation.published / deleted, localization.locale.published / unpublished / updated, localization.job.completed / failed
  • Locale-aware delivery, SEO files and customer-facing text可用
    API
    Delivery ?locale= (code or URL prefix) on /site, /pages, /globals, /collections, /catalog, /forms, /search, /seo/* and /feed with resolvedLocale / availableLocales / localePaths (collection items: localeSlugs), any locale's slug resolves to the record; /redirects rules carry locale; Customer API locale on deliverables, orders and unit open; SDK createKanorioMiddleware({ features: { locales } }), buildAlternates, requestLocaleOf, languageSwitcher, locale-scoped revalidate; CLI doctor i18n rules
    Elements
    locale on <KanorioProvider> (forms, login, curriculum and unit load the visitor's locale)
    託管網站
    Primary locale at the root, other locales under their prefix (/en/…), header language menu, per-locale llms.txt / rss.xml, one sitemap with xhtml:link, hreflang and x-default
    Webhooks
    cacheTags on every content event carry @<locale> so a translation going live refreshes only that locale

API 參考

Webhook 事件

  • content.translation.published · Fired when one record's translation in one locale goes live on its own (editor correction, Management API write, incremental or on-demand machine translation). cacheTags carry only that locale's tags. Not fired per record during a full-site translation job; see localization.job.completed.
  • content.translation.deleted · Fired when a live translation of one record in one locale is deleted; visitors see the primary-locale text until it is translated again.
  • localization.locale.published · Fired when a locale goes live for visitors and the Content Delivery API (a full-site translation job finished, or the owner published it). cacheTags is site:<id>: rebuild the language switcher and hreflang on every page.
  • localization.locale.unpublished · Fired when a live locale is taken offline or removed (removed: true); its URL prefix now 301-redirects to the primary locale.
  • localization.locale.updated · Fired when a live locale's URL prefix (change: path_prefix, previous holds the old prefix), its position in the language switcher (order) or the site's primary locale (primary) changes.
  • localization.job.completed · Fired when a full-site translation job finishes. cacheTags is locale:<code>: every response of that locale may have changed. A locale going live for the first time also fires localization.locale.published.
  • localization.job.failed · Fired when a full-site translation job fails (the model provider stayed unavailable or retries ran out; the daily limit only pauses a job). Retry it with localization.jobs.retry.

近期變更

  • 2026-11-04 Localization: automated emails follow the customer's language
  • 2026-11-04 Localization: publishing one locale needs the record's publish permission
  • 2026-11-04 Localization: more translatable fields (product details, variants, lessons, quizzes, store notes)
  • 2026-11-04 Localization: each locale can have its own URL slug
  • 2026-11-03 Localization is generally available; site export includes locales and translations
查看完整變更紀錄

給網站擁有者

在後台如何使用這項產品,請見說明中心。

開啟說明中心