# 語系與在地化

> Several locales in one site, with a primary locale, machine translation that costs no credits, locale-aware delivery and SEO, and the same contract for hosted and headless front ends.

> Markdown version of https://kanorio.com/zh-Hant/developers/products/localization. Append `.md` to any developer docs URL for this format. Index: https://kanorio.com/llms.txt · MCP: https://app.kanorio.com/api/mcp
>
> Translated from the English original: https://kanorio.com/en/developers/products/localization.md

Status: **Available**

網站擁有一個主要語系，並可新增更多語系。每個文字欄位皆保留其主要語系的數值；翻譯內容則儲存於旁邊的資料表中，每一筆記錄與語系各佔一行。新增語系時，系統會在背景翻譯整個網站，並於完成後發佈。託管網站與您建置的任何前端，皆透過相同的 `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` 與搜尋功能皆遵循相同的參數。請參閱 [讀取內容](https://kanorio.com/zh-Hant/developers/guides/read-content)。
- **使用 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](https://kanorio.com/zh-Hant/developers/webhooks)。
- **在前端進行路由與標籤。** `createKanorioMiddleware({ features: { locales: true } })` 會將主要語系的前綴重新導向至根目錄，提供 `/<prefix>/llms.txt` 與 `/<prefix>/rss.xml`，比對不含前綴的共享重新導向，並針對完整路徑比對語系重新導向（`locale` 設定）。`requestLocaleOf`、`buildAlternates` 與 `languageSwitcher`（傳入 `localePaths`）可讓您取得語系、標準網址 (canonical)、hreflang 以及與託管網站規則相同的語言選單。請參閱 [Next.js](https://kanorio.com/zh-Hant/developers/guides/nextjs) 與 [SDK 參考](https://kanorio.com/zh-Hant/developers/sdk)。
- **顧客端文字。** Customer API 與 `@kanorio/elements` 接受 `locale`；若未提供，則使用顧客記錄的語系。課程與單元標題、訂單項目名稱與完成證書皆遵循此設定。請參閱 [課程與成員](https://kanorio.com/zh-Hant/developers/guides/courses-and-members)。
- **自動化電子郵件。** 訂單、付款、運送、退款、登入與表單確認郵件會以顧客記錄的語系發送（若網站提供該語系），否則使用主要語系。若擁有者未自訂電子郵件，則使用內建措辭（每個網站語言皆有對應版本）。自訂電子郵件的翻譯方式與其他內容相同：其翻譯為 `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`。

## What the APIs expose

| Capability | Status | API | Elements | Hosted site | Webhooks |
| --- | --- | --- | --- | --- | --- |
| Locale set & translations (add a locale, full-site machine translation, review) | Available | 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 | `content.translation.published` / `deleted`, `localization.locale.published` / `unpublished` / `updated`, `localization.job.completed` / `failed` |
| Locale-aware delivery, SEO files and customer-facing text | Available | 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 | `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` | `cacheTags` on every content event carry `@<locale>` so a translation going live refreshes only that locale |

## API reference

- Management API: [Localization](https://kanorio.com/en/developers/management-api/localization) (16 operations)

## Webhook events

- `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.

Payloads: https://kanorio.com/en/developers/webhooks/events

## Recent changes

- 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

Full changelog: https://kanorio.com/en/developers/changelog

## For site owners

Dashboard help: https://kanorio.com/zh-Hant/help/multilingual-site
