跳到主要内容

国际化 - 使用 Crowdin

Docusaurus 的国际化系统 与任何翻译软件无关

您可以将 Docusaurus 与 您选择的工具和 SaaS 集成 ,只要您将 翻译文件放在正确的位置 即可。

我们记录了 Crowdin 的用法,作为一个可能的 集成示例

注意

这不是对 Crowdin 作为翻译 Docusaurus 网站的唯一选择的 认可 ,但 Facebook 成功地使用它来翻译文档项目,例如 JestDocusaurusReasonML

请参考 Crowdin 文档Crowdin 支持 获取帮助。

提示

使用此 社区驱动的 GitHub 讨论 来讨论与 Docusaurus + Crowdin 相关的任何内容。

Crowdin 概述

Crowdin 是一款翻译 SaaS,为 开源项目提供免费计划

我们推荐以下翻译工作流程:

  • 源文件 上传到 Crowdin(未翻译的文件)
  • 使用 Crowdin 翻译内容
  • 从 Crowdin 下载翻译 (本地化翻译文件)

Crowdin 提供了一个 CLI上传源文件下载翻译 ,允许您自动化翻译过程。

crowdin.yml 配置文件 对于 Docusaurus 来说很方便,并且允许 将本地化翻译文件下载到预期位置 (在 i18n/[locale]/.. 中)。

阅读 官方文档 以了解有关高级功能和不同翻译工作流程的更多信息。

Crowdin 教程

这是一个使用 Crowdin 将新初始化的英文 Docusaurus 网站翻译成法文的演练,并假设您已遵循 国际化教程

最终结果可以在 docusaurus-crowdin-example.netlify.app (代码库) 中看到。

准备 Docusaurus 站点

初始化一个新的 Docusaurus 站点:

npx create-docusaurus@latest website classic

添加法语的站点配置:

docusaurus.config.js
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
},
themeConfig: {
navbar: {
items: [
// ...
{
type: 'localeDropdown',
position: 'left',
},
// ...
],
},
},
// ...
};

翻译主页:

src/pages/index.js
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 项目

您的项目已创建,但目前为空。我们将在接下来的步骤中上传要翻译的文件。

创建 Crowdin 配置

此配置 (文档) 为 Crowdin CLI 提供了一个映射,以便理解:

  • 在哪里查找要上传的源文件(JSON 和 Markdown)
  • 翻译后在哪里下载文件(在 i18n/[locale] 中)

website 中创建 crowdin.yml

crowdin.yml
project_id: '123456'
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
# JSON 翻译文件
- source: /i18n/en/**/*
translation: /i18n/%two_letters_code%/**/%original_file_name%
# Docs Markdown 文件
- source: /docs/**/*
translation: /i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
# Blog Markdown 文件
- source: /blog/**/*
translation: /i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%

Crowdin 有自己声明源/翻译路径的语法:

  • **/*:子文件夹中的所有内容
  • %two_letters_code%:Crowdin 目标语言的 2 个字母的变体(在本例中为 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 install @crowdin/cli@3

添加 crowdin 脚本:

package.json
{
"scripts": {
// ...
"write-translations": "docusaurus write-translations",
"crowdin": "crowdin"
}
}

测试您可以运行 Crowdin CLI:

npm run crowdin -- --version

在您的计算机上设置 CROWDIN_PERSONAL_TOKEN 环境变量,以允许 CLI 使用 Crowdin API 进行身份验证。

提示

暂时,您可以使用 api_token: 'MY-TOKEN'crowdin.yml 中硬编码您的个人令牌。

上传源文件

website/i18n/en 中的默认语言生成 JSON 翻译文件:

npm run write-translations

上传所有 JSON 和 Markdown 翻译文件:

npm run crowdin upload

Crowdin CLI 上传 Docusaurus 源文件

您的源文件现在可在 Crowdin 界面上看到:https://crowdin.com/project/<MY_PROJECT_NAME>/settings#files

Crowdin UI 显示 Docusaurus 源文件

翻译源文件

https://crowdin.com/project/<MY_PROJECT_NAME> 上,单击法语目标语言。

Crowdin UI 显示法语翻译文件

翻译一些 Markdown 文件。

Crowdin UI 翻译 Markdown 文件

提示

使用“隐藏字符串”确保译者 不会翻译不应翻译的内容

  • 前置 matter:idslugtags ...
  • 警告:::::::note:::tip ...

Crowdin UI 隐藏字符串

翻译一些 JSON 文件。

Crowdin UI 翻译 JSON 文件

信息

JSON 翻译文件的 description 属性在 Crowdin 上可见,有助于翻译字符串。

提示

预翻译您的网站,并 手动更正预翻译错误(首先启用设置中的全局翻译内存)。

首先使用“隐藏字符串”功能,因为 Crowdin 过于乐观地进行预翻译。

下载翻译

使用 Crowdin CLI 下载已翻译的 JSON 和 Markdown 文件。

npm run crowdin download

已翻译的内容应下载到 i18n/fr 中。

在法语区域设置下启动您的站点:

npm run start -- --locale fr

确保您的网站现在已翻译成法语,网址为 http://localhost:3000/fr/

使用 CI 自动化

我们将配置 CI 以 在构建时下载 Crowdin 翻译 并将它们保存在 Git 之外。

website/i18n 添加到 .gitignore

在您的 CI 上设置 CROWDIN_PERSONAL_TOKEN 环境变量。

创建一个 npm 脚本以 sync Crowdin(提取源文件、上传源文件、下载翻译):

package.json
{
"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 规避语法:

# 如何部署 Docusaurus

要部署 Docusaurus,请运行以下命令:

````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 提供了一个“重复字符串”设置。

Crowdin 重复字符串选项设置

我们建议使用“隐藏”,但理想设置取决于您的版本差异程度。

注意

不使用“隐藏”会导致配额中的“源字符串”数量大幅增加,并会影响价格。

多实例插件

您需要为每个插件实例配置翻译文件。

如果您有一个 id=ios 的文档插件实例,您也需要配置这些源文件

  • website/ios
  • website/ios_versioned_docs(如果已版本化)

维护您的站点

有时,您会在 Git 上 删除或重命名源文件 ,Crowdin 将显示 CLI 警告:

Crowdin CLI:下载翻译警告

当您的源文件被重构时,您应该使用 Crowdin UI 手动更新您的 Crowdin 文件

Crowdin UI:重命名文件

VCS(Git)集成

Crowdin 为 GitHub 、GitLab、Bitbucket 提供多种 VCS 集成。

TL;DR

我们建议避免使用它们。

能够同时在 Git 和 Crowdin 中编辑翻译,并在两个系统之间进行 双向同步 本来是有帮助的。

实际上,由于以下几个原因, 它并没有非常可靠地工作

  • Crowdin -> Git 同步工作正常(带有拉取请求)
  • Git -> Crowdin 同步是手动的(您必须按下按钮)
  • Crowdin 用于将现有 Markdown 翻译与现有 Markdown 源匹配的启发式方法并非 100% 可靠,您必须在从 Git 同步后在 Crowdin UI 上验证结果
  • 两个用户同时在 Git 和 Crowdin 上编辑可能会导致翻译丢失
  • 它需要 crowdin.yml 文件位于存储库的根目录

上下文内本地化

Crowdin 具有 上下文内本地化 功能。

注意

不幸的是,由于技术原因,它尚无法工作,但我们有理由相信它可以解决。

Crowdin 将 Markdown 字符串替换为技术 ID,例如 crowdin:id12345,但它过于积极地这样做,包括隐藏的字符串,并弄乱了前置 matter、警告、JSX……

本地化编辑 URL

当用户浏览 /fr/doc1 中的页面时,编辑按钮默认会链接到 website/docs/doc1.md 中未本地化的文档。

您可以更倾向于让编辑按钮链接到 Crowdin 界面,方法是使用 editUrl 函数根据每个区域设置自定义编辑 URL。

docusaurus.config.js
const DefaultLocale = 'en';

export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
editUrl: ({locale, versionDocsDirPath, docPath}) => {
// 链接到法语文档的 Crowdin
if (locale !== DefaultLocale) {
return `https://crowdin.com/project/docusaurus-v2/${locale}`;
}
// 链接到英文文档的 GitHub
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 配置文件是使用版本控制和多实例的一个很好的例子:

crowdin.yml
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 一起使用,则应牢记这一点。