国际化 - 使用 Crowdin
Docusaurus 的国际化系统**与任何翻译软件无关**。
您可以将 Docusaurus 与**您选择的工具和 SaaS 集成**,只要您将**翻译文件放在正确的位置**即可。
我们记录了 Crowdin 的用法,作为**一个**可能的**集成示例**。
这**并非认可 Crowdin** 作为翻译 Docusaurus 站点唯一的选择,但 Facebook 已成功使用它来翻译文档项目,例如 Jest、Docusaurus 和 ReasonML。
请参阅Crowdin 文档 和Crowdin 支持 以获取帮助。
使用此社区驱动的 GitHub 讨论 来讨论与 Docusaurus + Crowdin 相关的所有内容。
Crowdin 概述
Crowdin 是一款翻译 SaaS,为开源项目提供免费计划。
我们推荐以下翻译工作流程
- 上传源文件到 Crowdin(未翻译的文件)
- 使用 Crowdin 翻译内容
- 从 Crowdin 下载翻译文件(本地化翻译文件)
Crowdin 提供了一个CLI 来上传源文件和下载翻译文件,允许您自动化翻译过程。
用于 Docusaurus 的crowdin.yml
配置文件 很方便,并允许将本地化翻译文件下载到预期位置(在 i18n/[locale]/..
中)。
阅读官方文档 以了解有关高级功能和不同翻译工作流程的更多信息。
Crowdin 教程
这是一个使用 Crowdin 将新初始化的英文 Docusaurus 网站翻译成法语的演练,并假设您已按照国际化教程操作。
最终结果可以在 docusaurus-crowdin-example.netlify.app (仓库) 中看到。
准备 Docusaurus 站点
初始化一个新的 Docusaurus 站点
npx create-docusaurus@latest website classic
添加法语的站点配置
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
},
themeConfig: {
navbar: {
items: [
// ...
{
type: 'localeDropdown',
position: 'left',
},
// ...
],
},
},
// ...
};
翻译首页
import React from 'react';
import Translate from '@docusaurus/Translate';
import Layout from '@theme/Layout';
export default function Home() {
return (
<Layout>
<h1 style={{margin: 20}}>
<Translate description="The homepage main heading">
Welcome to my Docusaurus translated site!
</Translate>
</h1>
</Layout>
);
}
创建 Crowdin 项目
在 Crowdin 上注册并创建一个项目。
使用英语作为源语言,法语作为目标语言。
您的项目已创建,但目前为空。我们将在后续步骤中上传要翻译的文件。
创建 Crowdin 配置
此配置(doc)为 Crowdin CLI 提供了一个映射,以便理解
- 在哪里找到要上传的源文件(JSON 和 Markdown)
- 翻译后在哪里下载文件(在
i18n/[locale]
中)
在 website
中创建 crowdin.yml
project_id: '123456'
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
# JSON translation files
- source: /i18n/en/**/*
translation: /i18n/%two_letters_code%/**/%original_file_name%
# Docs Markdown files
- source: /docs/**/*
translation: /i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
# Blog Markdown files
- source: /blog/**/*
translation: /i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%
Crowdin 有自己的语法来声明源/翻译路径
**/*
:子文件夹中的所有内容%two_letters_code%
:Crowdin 目标语言的两位代码(在本例中为fr
)**/%original_file_name%
:翻译将保留原始文件夹/文件层次结构
Crowdin CLI 警告并不总是容易理解。
我们建议
- 一次更改一项内容
- 任何配置更改后重新上传源文件
- 使用以
/
开头的路径(./
不起作用) - 避免使用
/docs/**/*.(md|mdx)
之类的花哨的通配符模式(不起作用)
访问令牌
api_token_env
属性定义了 Crowdin CLI 读取的**环境变量名称**。
您可以在您的个人资料页面上获取 个人访问令牌
。
您可以保留默认值 CROWDIN_PERSONAL_TOKEN
,并在您的计算机和 CI 服务器上将此环境变量设置为生成的访问令牌。
个人访问令牌授予对所有 Crowdin 项目的读写访问权限。
您**不应提交**它,并且最好为您的公司创建一个专用的Crowdin 账户,而不是使用个人账户。
其他配置字段
project_id
:可以硬编码,可以在https://crowdin.com/project/<MY_PROJECT_NAME>/settings#api
上找到preserve_hierarchy
:在 Crowdin UI 上保留文档的文件夹层次结构,而不是将所有内容都扁平化
安装 Crowdin CLI
本教程使用 CLI 版本 3.5.2
,但我们预计 3.x
版本将继续工作。
将 Crowdin CLI 作为 npm 包安装到您的 Docusaurus 站点中
- npm
- Yarn
- pnpm
npm install @crowdin/cli@3
yarn add @crowdin/cli@3
pnpm add @crowdin/cli@3
添加 crowdin
脚本
{
"scripts": {
// ...
"write-translations": "docusaurus write-translations",
"crowdin": "crowdin"
}
}
测试您是否可以运行 Crowdin CLI
- npm
- Yarn
- pnpm
npm run crowdin -- --version
yarn crowdin --version
pnpm run crowdin --version
在您的计算机上设置 CROWDIN_PERSONAL_TOKEN
环境变量,以允许 CLI 认证到 Crowdin API。
暂时,您可以在 crowdin.yml
中使用 api_token: 'MY-TOKEN'
硬编码您的个人令牌。
上传源文件
为 website/i18n/en
中的默认语言生成 JSON 翻译文件
- npm
- Yarn
- pnpm
npm run write-translations
yarn write-translations
pnpm run write-translations
上传所有 JSON 和 Markdown 翻译文件
- npm
- Yarn
- pnpm
npm run crowdin upload
yarn crowdin upload
pnpm run crowdin upload
您的源文件现在可以在 Crowdin 界面中看到:https://crowdin.com/project/<MY_PROJECT_NAME>/settings#files
翻译源文件
在 https://crowdin.com/project/<MY_PROJECT_NAME>
上,点击法语目标语言。
翻译一些 Markdown 文件。
使用 隐藏字符串
确保翻译人员**不会翻译不应该翻译的内容**
- 前置 matter:
id
、slug
、tags
... - 警告:
:::
、:::note
、:::tip
...
翻译一些 JSON 文件。
JSON 翻译文件的 description
属性在 Crowdin 中可见,以帮助翻译字符串。
预翻译 您的站点,并**手动修复预翻译错误**(首先在设置中启用全局翻译内存)。
首先使用 隐藏字符串
功能,因为 Crowdin 预翻译的内容过于乐观。
下载翻译文件
使用 Crowdin CLI 下载翻译后的 JSON 和 Markdown 文件。
- npm
- Yarn
- pnpm
npm run crowdin download
yarn crowdin download
pnpm run crowdin download
翻译后的内容应下载到 i18n/fr
中。
在法语区域设置中启动您的站点
- npm
- Yarn
- pnpm
npm run start -- --locale fr
yarn run start --locale fr
pnpm run start --locale fr
确保您的网站现在已翻译成法语,网址为 http://localhost:3000/fr/
。
使用 CI 自动化
我们将配置 CI 以在构建时下载 Crowdin 翻译并将它们保留在 Git 之外。
将 website/i18n
添加到 .gitignore
中。
在您的 CI 上设置 CROWDIN_PERSONAL_TOKEN
环境变量。
创建一个 npm 脚本以 sync
Crowdin(提取源文件、上传源文件、下载翻译文件)
{
"scripts": {
"crowdin:sync": "docusaurus write-translations && crowdin upload && crowdin download"
}
}
在您的 CI 中调用 npm run crowdin:sync
脚本,就在构建 Docusaurus 站点之前。
保持部署预览速度快:不要下载翻译文件,并使用 npm run build -- --locale en
用于功能分支。
Crowdin 不太支持同时进行多个上传/下载操作:最好只将翻译内容包含在生产部署中,并将部署预览保持为未翻译状态。
Crowdin 高级主题
MDX
请特别注意 MDX 文档中的 JSX 片段!
Crowdin **官方不支持 MDX**,但他们添加了对 **.mdx
扩展名**的支持,并将此类文件解释为 Markdown(而不是纯文本)。
MDX 问题
Crowdin 将 JSX 语法视为嵌入式 HTML,并在您下载翻译时可能会弄乱 JSX 标记,导致站点由于无效的 JSX 而无法构建。
使用简单字符串属性的简单 JSX 片段,如 <Username name="Sebastien"/>
将正常工作;使用对象/数组属性的更复杂的 JSX 片段,如 <User person={{name: "Sebastien"}}/>
更有可能由于语法不像是 HTML 而失败。
MDX 解决方案
我们建议将复杂的嵌入式 JSX 代码提取为单独的独立组件。我们还添加了一个 mdx-code-block
逃生语法
# How to deploy Docusaurus
To deploy Docusaurus, run the following command:
````mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs>
<TabItem value="bash" label="Bash">
```bash
GIT_USER=<GITHUB_USERNAME> yarn deploy
```
</TabItem>
<TabItem value="windows" label="Windows">
```batch
cmd /C "set "GIT_USER=<GITHUB_USERNAME>" && yarn deploy"
```
</TabItem>
</Tabs>
````
这将
- 被 Crowdin 解释为代码块(并且在下载时不会弄乱标记)
- 被 Docusaurus 解释为常规 JSX(就像它没有被任何代码块包裹一样)
- 不幸的是,无法使用 MDX 工具(IDE 语法高亮、Prettier 等)
文档版本控制
为 website/versioned_docs
文件夹配置翻译文件。
创建新版本时,源字符串通常与当前版本 (website/docs
) 非常相似,并且您不希望一次又一次地翻译新版本文档。
Crowdin 提供了“复制字符串”设置。
我们建议使用“隐藏”,但理想的设置取决于版本之间的差异程度。
不使用“隐藏”会导致配额中的“源字符串”数量大幅增加,并会影响定价。
多实例插件
您需要为每个插件实例配置翻译文件。
如果您有一个 id=ios
的文档插件实例,则也需要配置这些源文件
website/ios
website/ios_versioned_docs
(如果已版本化)
维护您的站点
有时,您会在 Git 上**删除或重命名源文件**,Crowdin 会显示 CLI 警告
当您的源代码重构后,您应该使用 Crowdin UI **手动更新您的 Crowdin 文件**
VCS(Git)集成
Crowdin 为 GitHub、GitLab、Bitbucket 提供多种 VCS 集成。
我们建议避免使用它们。
能够在 Git 和 Crowdin 中同时编辑翻译并在这两个系统之间进行**双向同步**本来会很有帮助。
实际上,由于以下几个原因,**它运行得不太可靠**
- Crowdin -> Git 同步工作正常(使用拉取请求)
- Git -> Crowdin 同步是手动的(您必须按下按钮)
- Crowdin 用于将现有 Markdown 翻译与现有 Markdown 源进行匹配的启发式方法并非 100% 可靠,您必须在从 Git 同步后的 Crowdin UI 上验证结果
- 两个用户同时在 Git 和 Crowdin 上进行编辑会导致翻译丢失
- 它要求
crowdin.yml
文件位于存储库的根目录
上下文本地化
Crowdin 具有 上下文本地化 功能。
不幸的是,由于技术原因,它尚不可用,但我们有理由相信它可以解决。
Crowdin 将 Markdown 字符串替换为技术 ID,例如 crowdin:id12345
,但它过于激进地执行此操作,包括隐藏的字符串,并弄乱了前置信息、警告、JSX 等……
本地化编辑 URL
当用户浏览 /fr/doc1
处的页面时,编辑按钮默认会链接到 website/docs/doc1.md
处的未本地化文档。
您可能希望编辑按钮链接到 Crowdin 接口,而不是使用 editUrl
函数在每个区域设置的基础上自定义编辑 URL。
const DefaultLocale = 'en';
export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
editUrl: ({locale, versionDocsDirPath, docPath}) => {
// Link to Crowdin for French docs
if (locale !== DefaultLocale) {
return `https://crowdin.com/project/docusaurus-v2/${locale}`;
}
// Link to GitHub for English docs
return `https://github.com/facebook/docusaurus/edit/main/website/${versionDocsDirPath}/${docPath}`;
},
},
blog: {
editUrl: ({locale, blogDirPath, blogPath}) => {
if (locale !== DefaultLocale) {
return `https://crowdin.com/project/docusaurus-v2/${locale}`;
}
return `https://github.com/facebook/docusaurus/edit/main/website/${blogDirPath}/${blogPath}`;
},
},
},
],
],
};
目前**无法链接到 Crowdin 中的特定文件**。
示例配置
**Docusaurus 配置文件**是使用版本控制和多实例的一个很好的示例
project_id: '428890'
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
languages_mapping: &languages_mapping
two_letters_code:
pt-BR: pt-BR
files:
- source: /website/i18n/en/**/*
translation: /website/i18n/%two_letters_code%/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/docs/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/community/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs-community/current/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/versioned_docs/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/blog/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/src/pages/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-pages/**/%original_file_name%
ignore: [/**/*.js, /**/*.jsx, /**/*.ts, /**/*.tsx, /**/*.css]
languages_mapping: *languages_mapping
机器翻译 (MT) 问题:链接/图像处理
Crowdin 最近对 Markdown 文件格式进行了一些重大更改,现在链接的处理方式与之前不同。之前它们被视为标签,但现在它们显示为纯文本。由于这些更改,纯文本链接被传递给 MT 引擎,后者尝试翻译目标,从而破坏了翻译(例如:字符串 Allez voir [ma merveilleuse page](/ma-merveilleuse-page)
被翻译为 Check out [my wonderful page](/my-wonderful-page)
,这会破坏 docusaurus i18n 工作流程,因为页面名称不应翻译)。
截至 2023 年 12 月 7 日,他们不打算更改链接处理逻辑,因此如果您计划将 Crowdin 与 MT 一起使用,请牢记这一点。