i18n - 教學
本教學將帶您深入了解 Docusaurus i18n 系統 的基本知識。
我們將在 新初始化的英文 Docusaurus 網站 中新增 法文 翻譯。
使用 npx create-docusaurus@latest website classic
初始化一個新網站(像 這個)。
設定你的網站
修改 docusaurus.config.js
來新增對法文語言的 i18n 支援。
網站組態
使用 網站 i18n 組態 來宣告 i18n 的區域設定
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'fa'],
localeConfigs: {
en: {
htmlLang: 'en-GB',
},
// You can omit a locale (e.g. fr) if you don't need to override the defaults
fa: {
direction: 'rtl',
},
},
},
};
地區名稱用於翻譯檔案的位置,以及您所翻譯地區的基本 URL。在建置所有地區時,僅有預設地區的名稱會被省略在基本 URL 中。
Docusaurus 使用地區名稱來提供**合理的預設值**:<html lang="...">
屬性、地區標籤、行事曆格式等。您可以使用 localeConfigs
來自訂這些預設值。
佈景主題設定
新增一個**導覽列項目**類型為 localeDropdown
,讓使用者可以選擇他們想要的語言
export default {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};
當使用者使用下拉式選單變更地區時,您可以傳遞一個查詢參數,該參數將附加到 URL 裡(例如:queryString: '?persistLocale=true'
)。
這對於在您的伺服器上實作自動地區偵測非常有用。例如,您可以使用這個參數來將使用者的偏好地區儲存在 cookie 裡。
啟動您的網站
使用您選擇的地區,在開發模式下啟動您的地區化網站
- npm
- Yarn
- pnpm
npm run start -- --locale fr
yarn run start --locale fr
pnpm run start --locale fr
您的網站位址為 https://127.0.0.1:3000/fr/
。
我們尚未提供任何翻譯,因此該網站大多未翻譯。
Docusaurus 提供**預設翻譯**給佈景主題的一般標籤,例如分頁的「下一頁」和「上一頁」。
請協助我們完成這些**預設翻譯。
每個地區都是一個**獨立的單頁應用程式**:不可能同時啟動所有地區的 Docusaurus 網站。
翻譯您的網站
法語區的翻譯資料都儲存在 website/i18n/fr
中。各個外掛會在其對應的資料夾裡提供自身的翻譯內容,而 code.json
檔案定義 React 程式碼中所有使用的文字標籤。
複製檔案後,使用 npm run start -- --locale fr
重新啟動你的網站。編輯現有檔案時,熱重載功能會發揮更好的作用。
翻譯你的 React 程式碼
對於你自行撰寫的 React 程式碼(例如 React 頁面、React 元件等),你將會使用translation API。
在你的 React 程式碼中找出所有會顯示給使用者的文字標籤,並利用 translation API 標示它們。共有兩種 API
<Translate>
元件會將字串包覆為 JSX 元素translate()
回呼會接收訊息並傳回字串
使用在語意上比較符合情境的 API。例如,<Translate>
可以用作 React 子代,而對於預期使用字串的屬性,則可以使用回呼。
- 使用前
- 使用後
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
export default function Home() {
return (
<Layout>
<h1>Welcome to my website</h1>
<main>
You can also visit my
<Link to="https://docusaurus.dev.org.tw/blog">blog</Link>
<img
src="/img/home.png"
alt="Home icon"
/>
</main>
</Layout>
);
}
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
import Translate, {translate} from '@docusaurus/Translate';
export default function Home() {
return (
<Layout>
<h1>
<Translate>Welcome to my website</Translate>
</h1>
<main>
<Translate
id="homepage.visitMyBlog"
description="The homepage message to ask the user to visit my blog"
values={{
blogLink: (
<Link to="https://docusaurus.dev.org.tw/blog">
<Translate
id="homepage.visitMyBlog.linkLabel"
description="The label for the link to my blog">
blog
</Translate>
</Link>
),
}}>
{'You can also visit my {blogLink}'}
</Translate>
<img
src="/img/home.png"
alt={
translate({
message: 'Home icon',
description: 'The homepage icon alt message',
})
}
/>
</main>
</Layout>
);
}
Docusaurus 特意提供一個非常小巧精簡的翻譯執行時期環境,且僅支援利用 佔位符插入 子集執行的基本 ICU 訊息格式。
大多數的文件網站通常是靜態的,不需要進階的 i18n 功能(複數、性別等)。對於進階使用案例,使用套件庫,例如 react-intl。
docusaurus write-translations
命令會在您的網站中靜態分析所有使用的 React 程式碼檔案,擷取對這些 API 的呼叫,並將它們集中在 code.json
檔案中。翻譯檔案會儲存在 ID 對應到翻譯訊息物件(包括已翻譯標籤和標籤描述)的對應中。在呼叫翻譯 API(
或 translate()
)時,您需要指定預設未翻譯訊息或 ID,以便 Docusaurus 正確將每個翻譯項目與 API 呼叫關聯。
docusaurus write-translations
命令只會針對您的程式碼做靜態分析。它不會實際執行您的網站。因此,動態訊息無法擷取,因為該訊息是表達式,而不是字串
const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
];
function ItemsList() {
return (
<ul>
{/* DON'T DO THIS: doesn't work with the write-translations command */}
{items.map((item) => (
<li key={item.id}>
<Translate>{item.title}</Translate>
</li>
))}
<ul>
);
}
這在執行時期仍然執行正確。然而,在未來,我們可能會提供「無執行時期」機制,讓翻譯可以透過 Babel 轉換直接內嵌在 React 程式碼中,而不必在執行時期呼叫 API。因此,要達到讓它未來適用,您應該總是偏好能被靜態分析的訊息。例如,我們可以將上方的程式碼重構為
const items = [
{id: 1, title: <Translate>Hello</Translate>},
{id: 2, title: <Translate>World</Translate>},
];
function ItemsList() {
return (
<ul>
{/* The titles are now already translated when rendering! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}
您可以將對翻譯 API 的呼叫視為純粹的標記,告訴 Docusaurus「這裡有一個要替換成已翻譯訊息的文字標籤」。
複數化方式
當您執行 write-translations
時,您會注意到有些標籤是已複數化的
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}
每種語言都會有一列 可能的複數類別。Docusaurus 會將它們排列成 ["zero", "one", "two", "few", "many", "other"]
的順序。例如,因為英文(en
)有兩種複數形式(「單數」和「其他」),所以翻譯訊息有兩種標籤,以直線(|
)分隔。對於波蘭文(pl
)有三種複數形式(「單數」、「少數」和「多數」),您會按順序提供三個標籤,再以直線連接起來。
您也可以將自己的程式碼訊息變成複數
import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';
function ItemsList({items}) {
// `usePluralForm` will provide the plural selector for the current locale
const {selectMessage} = usePluralForm();
// Select the appropriate pluralized label based on `items.length`
const message = selectMessage(
items.length,
translate(
{message: 'One item|{count} items'},
{count: items.length},
),
);
return (
<>
<h2>{message}</h2>
<ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}<ul>
</>
);
}
Docusaurus 使用 Intl.PluralRules
來解決並選擇複數形式。為 selectMessage
提供正確數量與順序的複數形式很重要。
翻譯外掛數據
JSON 翻譯檔案會使用在你的程式碼中穿插的所有內容
- React 程式碼,包含你標示在上面的已翻譯標籤
- 主題設定檔中的導覽列和頁尾標籤
sidebars.js
中的 Docs 側邊欄類別標籤- 外掛選項中的部落格側邊欄標題
- ...
執行 write-translations 指令
- npm
- Yarn
- pnpm
npm run write-translations -- --locale fr
yarn write-translations --locale fr
pnpm run write-translations --locale fr
它將提取你需翻譯的 JSON 翻譯檔案並加以初始化。根目錄中的 code.json
檔案包含從原始程式碼提取的所有翻譯 API 呼叫,這些呼叫可能是你編寫的,或由主題提供的,其中有些可能已經預設翻譯。
{
// No ID for the <Translate> component: the default message is used as ID
"Welcome to my website": {
"message": "Welcome to my website"
},
"home.visitMyBlog": {
"message": "You can also visit my {blog}",
"description": "The homepage message to ask the user to visit my blog"
},
"homepage.visitMyBlog.linkLabel": {
"message": "Blog",
"description": "The label for the link to my blog"
},
"Home icon": {
"message": "Home icon",
"description": "The homepage icon alt message"
}
}
外掛和主題也會寫入自己的 JSON 翻譯檔案,例如
{
"title": {
"message": "My Site",
"description": "The title in the navbar"
},
"item.label.Docs": {
"message": "Docs",
"description": "Navbar item with label Docs"
},
"item.label.Blog": {
"message": "Blog",
"description": "Navbar item with label Blog"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}
在 i18n/fr
的 JSON 檔案中翻譯 message
屬性,你的網站版面和首頁現在應該已經翻譯完成。
翻譯 Markdown 檔案
官方的 Docusaurus 內容外掛廣泛使用 Markdown/MDX 檔案,並允許你翻譯它們。
翻譯文件
將你的文件 Markdown 檔案從 docs/
複製到 i18n/fr/docusaurus-plugin-content-docs/current
,並翻譯它們
mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
請注意,docusaurus-plugin-content-docs
外掛始終依據版本區分其內容。./docs
資料夾中的資料將翻譯為 current
子資料夾和 current.json
檔案。關於「current」的進一步資訊,請參閱文件版本指南。
翻譯部落格
將你的部落格 Markdown 檔案複製到 i18n/fr/docusaurus-plugin-content-blog
,並翻譯它們
mkdir -p i18n/fr/docusaurus-plugin-content-blog
cp -r blog/** i18n/fr/docusaurus-plugin-content-blog
翻譯網頁
將你的網頁 Markdown 檔案複製到 i18n/fr/docusaurus-plugin-content-pages
,並翻譯它們
mkdir -p i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/**.md i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/**.mdx i18n/fr/docusaurus-plugin-content-pages
我們只會複製 .md
和 .mdx
檔案,因為 React 頁面已經透過 JSON 翻譯檔案翻譯了。
預設情況下,Markdown 標題 ### Hello World
會產生 ID hello-world
。其他文件可以用 [link](#hello-world)
連結這個標題。然而,翻譯標題後會變成 ### Bonjour le Monde
,其 ID 則會變成 bonjour-le-monde
。
由於所有錨點連結都必須翻譯,因此產生 ID 未必適用於在地化網站。
- [link](#hello-world).
+ [link](#bonjour-le-monde)
若您的網站有在地化需求,建議您使用 明確標題 ID。
部署您的網站
你可以選擇在 單一網域或 多個(次級)網域之下部署您的網站。
單網域部署
執行以下指令
- npm
- Yarn
- pnpm
npm run build
yarn build
pnpm run build
Docusaurus 會在 每個地區設定中組建單一頁面應用程式
website/build
:預設的英文website/build/fr
:法文
現在您可以 部署 build
資料夾至您選擇的靜態託管解決方案。
Docusaurus 網站使用此策略
根據慣例,靜態託管供應商通常會將 /unknown/url
重新導向至 /404.html
,總是顯示 英文 404 頁面。
在地化您的 404 頁面,方法是設定您的主機將 /fr/*
重新導向至 /fr/404.html
。
這並不總是可行,而且視您的主機而定:GitHub Pages 無法這麼做,但 Netlify 可以。
多網域部署
您也可以為單一地區設定組建您的網站
- npm
- Yarn
- pnpm
npm run build -- --locale fr
yarn build --locale fr
pnpm run build --locale fr
Docusaurus 不會加上 /fr/
URL 前置詞。
在您 靜態託管供應商 上
- 為每個地區設定建立一個部署
- 設定適當的組建指令,使用
--locale
選項 - 為每個部署設定您選擇的(次級)網域
此策略無法搭配 GitHub Pages 使用,因為它只允許 單一部署。
混合式
可以讓一些地區設定使用子路徑,而其他地區設定使用次網域。
也可以將每個地區設定部署為單獨的子網域,並在 CDN 層級將這些子網域組裝成單一統一網域。
- 將您的網站部署為
fr.docusaurus.io
- 設定 CDN,讓它透過
docusaurus.io/fr
提供服務
管理翻譯
Docusaurus 不在乎你如何管理你的翻譯:它需要的只是所有翻譯檔案(JSON、Markdown 或其他資料檔案)在建置期間在檔案系統中可用。不過,身為網站建立者,你需要考慮翻譯的管理方式,以便翻譯貢獻者順利合作。
我們將分享兩種常見的翻譯合作策略:使用 Git 和 使用 Crowdin.