# General Translation Knowledge Base: 如何在不破坏语法的前提下翻译 Markdown 和 MDX？
URL: https://generaltranslation.com/zh/kb/translate-markdown-files.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 翻译面向读者的文本，同时保留可执行代码、导入语句、JSX 组件名称和机器内部标识符。General Translation 可直接处理 Markdown 和 MDX，包括用于显示文本的属性和 frontmatter 标题，并在文档更新时复用匹配的译文。发布前，请审校本地化后的文件并运行站点构建。
Category: 翻译
Last updated: 2026-10-30
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Markdown 文件中既有正文，也有技术语法。MDX 还通过 `import` 语句、JSX 组件和 `{expressions}` 引入了 JavaScript，这些内容在翻译后仍须能被编译器正确解析。翻译前，先确定哪些字段包含显示文本：组件的 `title` 可能需要翻译，而其 `id` 则必须保持不变。

## Video

The video is narrated in English, with English captions.

[How do I translate Markdown and MDX without breaking syntax?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-translate-markdown-files.mp4) (48秒)

Translate prose, image alt text, frontmatter titles and descriptions, and display-text component props. Keep code blocks, inline code, imports, JSX component names, frontmatter keys, and link URLs unchanged, quote translated YAML values, then run your site's build. With General Translation, add an mdx or md entry under files in `gt.config.json` and run `npx gt translate`.

## Markdown 经过通用翻译器后会出现哪些问题

如果翻译器把文件视为纯文本，就会把其中所有内容都当作自然语言来翻译。需要排查的问题如下：

* **代码块和内联代码。** 命令和标识符可能被翻译，例如 `npm install` 可能变成 `npm installer`。
* **链接 URL 和锚点。** 链接中的 slug 或 `#fragment` 可能被翻译，导致链接失效。翻译后的标题还会生成新的 ID，导致所有指向这些标题的 `#anchor` 链接失效；正因如此，Docusaurus 建议使用[显式标题 ID](https://docusaurus.io/docs/i18n/tutorial#translate-markdown-files)。
* **Frontmatter。** `title` 等键可能被翻译，`slug` 的值可能被改动，翻译后的值也可能破坏 YAML 格式。法语习惯在冒号前加空格，因此 `title: Installer la CLI : guide rapide` 是无效的 YAML (`yaml` 解析器会将其报告为嵌套映射) 。这个值需要加引号。
* **HTML 属性。** `alt` 和 `title` 的文本需要翻译。`class` 及其他标识符应保持不变；`src` 或 `href` 只能通过显式的本地化资源或 URL 映射来更改。
* **MDX 导入和 JSX。** 如果 `import Tabs from '@theme/Tabs'` 被当作句子翻译，或者 `<Tabs>` 变成了 `<Onglets>`，构建就会失败。[Docusaurus Crowdin 指南](https://docusaurus.io/docs/i18n/crowdin#mdx)提醒，把 JSX 当作 HTML 解析的工具可能生成无效的 JSX，其中值为对象或数组的属性最容易出错。
* **提示块 (Admonitions) 。** Docusaurus 只将 `:::note`、`:::tip`、`:::info`、`:::warning` 和 `:::danger` 识别为[关键字](https://docusaurus.io/docs/markdown-features/admonitions)。翻译后的 `:::astuce` 不在其列，因此提示块会被渲染为纯文本。
* **表格。** GFM 表格只有在表头行与分隔行的单元格数量一致时才会被识别，且单元格内的字面竖线必须转义为 `\|` ([GFM 规范](https://github.github.com/gfm/#tables-extension-)) 。如果翻译器在单元格内加入了竖线或换行，该行就会被破坏。

下面是一个源文件，以及一个集齐上述所有问题的输出示例。该示例只是把这些问题集中展示，并非某个特定工具的实际输出。

```mdx
---
title: Install the CLI
slug: /install
---

import Tabs from '@theme/Tabs';

## Install the CLI {/* #install */}

Run `npm install my-cli`, then read the [setup guide](/docs/setup#api-keys).

:::tip
Use <Tabs groupId="pm">a package manager</Tabs> you already have.
:::
```

```mdx
---
titre: Installer la CLI : guide rapide
slug: /installer
---

importer Tabs depuis '@theme/Tabs';

## Installer la CLI {/* #installer */}

Exécutez `npm installer my-cli`, puis lisez le [guide](/docs/configuration#cles-api).

:::astuce
Utilisez <Onglets groupId="gp">un gestionnaire de paquets</Onglets> que vous avez déjà.
:::
```

第二个文件中出现了一系列问题：frontmatter 键被翻译了、YAML 格式无效、slug 被改动、导入语句无法被 MDX 解析、标题 ID 变了、命令被破坏、链接失效、提示块类型无法识别，还引用了一个根本不存在的组件。

## 翻译 Markdown 和 MDX 的方法

### a) Google 或 DeepL 的文档翻译

[Google Cloud Translation](https://docs.cloud.google.com/translate/docs/supported-formats) 的文档翻译功能 (Advanced 版) 支持 Word、PDF、PowerPoint 和 Excel 文件，但不支持 Markdown；其文本翻译功能则支持纯文本或 HTML。[DeepL API](https://developers.deepl.com/docs/api-reference/document) 将 Markdown (`.md`) 文档翻译标注为 beta 功能，且并未列出 MDX。无论选用哪一种，都应先用自己的文件测试输出效果，确认可靠后再交给它处理代码块和 frontmatter。

### b) 使用 AST 将正文与语法分离

[remark](https://github.com/remarkjs/remark) 会将 Markdown 解析为 [mdast](https://github.com/syntax-tree/mdast) 树。下面的提取示例会遍历 `text` 节点，同时跳过代码、属性和 frontmatter。它可以作为检查内容的起点，但并不是一条完整的翻译流水线：

```js
// extract.mjs: npm i unified remark-parse remark-stringify remark-mdx
//   remark-frontmatter remark-gfm remark-directive unist-util-visit
import { readFileSync } from 'node:fs';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkFrontmatter from 'remark-frontmatter';
import remarkGfm from 'remark-gfm';
import remarkMdx from 'remark-mdx';
import remarkDirective from 'remark-directive';
import remarkStringify from 'remark-stringify';
import { visit } from 'unist-util-visit';

const processor = unified()
  .use(remarkParse)
  .use(remarkFrontmatter, ['yaml']) // frontmatter 会被解析为单个 `yaml` 节点
  .use(remarkGfm)                   // 表格
  .use(remarkMdx)                   // import/export 和 JSX
  .use(remarkDirective)             // :::tip 提示框
  .use(remarkStringify);

const tree = processor.parse(readFileSync(process.argv[2], 'utf8'));

// 此演示仅提取 text 节点。在生产环境的翻译器中，属性和
// frontmatter 中的显示文本需要单独处理。
const segments = [];
visit(tree, 'text', (node) => {
  if (node.value.trim()) segments.push(node);
});

console.log(segments.map((n) => JSON.stringify(n.value)).join('\n'));

// 模拟翻译调用：原地替换每个片段。
for (const node of segments) node.value = node.value.toUpperCase();
console.log('\n' + processor.stringify(tree));
```

以上面的源文件为输入，并额外加入一个围栏 `bash` 代码块和一个两列表格，运行 `node extract.mjs guide.mdx` 后输出了以下片段 (节选) ：

```text
"Install the CLI "
"Run "
", then read the "
"setup guide"
"."
"Use "
"a package manager"
" you already have."
```

重新序列化后的文件保留了 frontmatter 内容、import 语句、标题 ID、内联代码、链接目标、提示块名称、JSX 属性和代码块内容，同时将文本节点转换成了大写。不过，它并没有逐字节保留所有格式。我们发现了三个局限：

* **句子被拆得支离破碎。** &quot;Run … then read the … setup guide&quot; 被拆成了五个片段，译者因此无法围绕代码和链接调整语序。生产环境中的脚本会以整段为单位翻译，并用占位符替代内联节点。
* **部分正文不在 `text` 节点中。** 图片的 `alt` 文本、JSX 属性值 (如 `title` 属性) 以及 frontmatter 中 `title` 等字段的值，都需要单独处理。
* **输出会被重新格式化。** `remark-stringify` 重新对齐了表格列宽，因此差异中会出现你并未改动的行。

解析还能尽早暴露语法错误。Mintlify 风格的 `{#install}` 标题后缀会导致 `remark-mdx` 报错 &quot;Could not parse expression with acorn&quot;，因为在 MDX 中，花括号标志着 JavaScript 表达式的开始。Docusaurus 也支持注释形式 `{/* #install */}`，可以通过 `docusaurus write-heading-ids --syntax mdx-comment` 自动写入。

大写替换只能体现解析器选中了哪些文本，并不能衡量翻译质量。在启用翻译流水线之前，请将受保护字段与源文件逐一比对，验证 YAML 和 MDX 语法，并实际运行一次站点构建，以排查失效的导入、链接或框架专用组件。

### c) 翻译管理系统

翻译管理系统 (TMS) 会替你解析文件。Crowdin 原生支持 [Markdown](https://store.crowdin.com/md) 和 [MDX](https://store.crowdin.com/mdx)，其[解析器配置](https://support.crowdin.com/parsers-configuration/)可以排除代码块和指定的 frontmatter 元素；MDX 文件默认按 MDX v1 上传，如需使用 v2，可选择 `mdx_v2` 类型。不过，你仍需映射源路径和输出路径、在 CI 中同步文件，并自行处理被解析器误读的 JSX。

### d) 通过规则提示 LLM

将整个文件交给模型，可以保留段落上下文。请明确需要翻译的显示文本字段，例如正文、图片 alt 文本、frontmatter 中的 `title` 和 `description`，以及指定的组件属性。代码、结构性键、导入语句、JSX 组件名称和 `:::` 关键字须保持不变；URL 只能按照你的区域设置映射进行修改，且 YAML 引号必须合法有效。提示中的规则无法强制执行，因此请解析输出结果、编译 MDX，并将受保护的内容与源文件逐一比对。

### 对比

| 方法                      | 理解 Markdown 结构                        | MDX 和 JSX              | Frontmatter        | 保持译文同步          | 所需投入              |
| ----------------------- | ------------------------------------- | ---------------------- | ------------------ | --------------- | ----------------- |
| Google 或 DeepL 文档翻译     | DeepL 的 `.md` 支持处于 beta 阶段；Google 不支持 | 未说明                    | 未经测试，需自行验证         | 逐个文件重新运行        | 低，另需检查            |
| remark 脚本               | 支持，由你决定处理哪些节点                         | 支持，需配合 `remark-mdx`    | 需自行处理              | 需自行编写变更检测       | 高                 |
| TMS (Crowdin)           | 支持                                    | 原生支持，但官方文档注明了 JSX 相关限制 | 可排除指定的键            | 在 CI 中通过 CLI 同步 | 中                 |
| 基于规则的 LLM               | 仅靠指令约束                                | 仅靠指令约束                 | 仅靠指令约束             | 需自行编写脚本         | 中，另需检查            |
| General Translation CLI | 专门处理 Markdown                         | 专门处理 MDX               | 翻译 Mintlify 的标题和描述 | 重复运行时复用匹配的译文    | 配置源路径、审阅输出、运行站点构建 |

如果只是一次性翻译某个 `.md` 文件并手动审阅，可以使用 DeepL 的 beta 版 Markdown 支持。如果需要完全掌控一小批稳定的文件，可以编写 remark 脚本。如果译者在 TMS 的编辑器中工作，就选用 TMS。如果只需快速生成草稿，再自行比对差异，可以使用 LLM 提示词。对于随版本发布持续变化的文档，请选择 General Translation：它负责生成和复用译文，翻译后的文件则始终保留在你的代码仓库中。

## 如何使用 General Translation 翻译 Markdown 和 MDX

如果 Markdown 和 MDX 文件存放在频繁变更的代码仓库中，可以借助 General Translation 的 CLI `gt` 在每次运行时自动翻译。它能够翻译 [MDX 和 Markdown 文件](/docs/cli/reference/formats/mdx-md-files)，同时保留原有的语法和格式。按照 [CLI 快速入门](/docs/cli/quickstart)运行 [`npx gt init`](/docs/cli/reference/commands/init) 后，在 `gt.config.json` 的 `files` 下添加 `mdx` 或 `md` 条目：

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "ja"],
  "files": {
    "mdx": { "include": ["docs/[locale]/**/*.mdx"] },
    "md": { "include": ["docs/[locale]/**/*.md"] }
  }
}
```

然后运行 [`npx gt translate`](/docs/cli/reference/commands/translate)。CLI 会从 `docs/en/` 读取源文件，并将译文写入 `docs/fr/` 和 `docs/ja/`。对于文档，以下几点行为值得注意：

* **标题 ID。** Mintlify 风格的 `{#id}` 后缀会保留在对应的标题上 (需要 `gt` 2.17.3 或更高版本) 。
* **Frontmatter。** 对于 Mintlify 站点，frontmatter 中的标题和描述也会被翻译。
* **增量运行。** 先前运行中匹配的译文会被复用，只有新增或更改的内容才会被翻译并计费。`--force` 会重新翻译全部内容，并覆盖本地修改。
* **手动修改。** 将修改同步回平台需要主动启用，可使用 [`npx gt translate --save-local`](/docs/cli/reference/commands/translate) 或 [`npx gt save-local`](/docs/cli/reference/commands/save-local)。
* **链接与导入。** 按区域设置重写 URL、导入语句和资源路径目前仍处于实验阶段，需通过 `--experimental-localize-static-urls` 等选项启用。

建议在构建之前[在 CI 中](/docs/cli/guides/generating-translations)运行该命令，将产品术语维护在与应用共享的[词汇表](/docs/platform/dashboard/guides/defining-context-for-translations)中，并在 [Dashboard 编辑器](/docs/platform/dashboard/guides/reviewing-translations)中审校措辞。发布前，请针对每个区域设置运行构建和链接检查。 (如需了解更全面的取舍，请参阅 [General Translation 与 Google Translate 对比](/kb/general-translation-vs-google-translate)以及 [General Translation 与 Crowdin 对比](/kb/general-translation-vs-crowdin)。)

### MDX 组件的哪些部分需要翻译？

General Translation 会区分读者看到的文本与站点使用的内部标识符。
在下面的源示例中，提示块的标题和正文一样需要翻译：

```mdx title="docs/en/deployment.mdx"
---
title: Deployment guide
slug: deployment-guide
---

import { Callout } from '@/components/Callout';

<Callout id="backup" type="warning" title="Back up your database first">
  Keep a backup before deploying.
</Callout>
```

| 源内容部分                            | 处理方式                   |
| -------------------------------- | ---------------------- |
| Frontmatter `title`              | 翻译页面标题                 |
| 提示块 `title` 和正文                  | 翻译可见文字                 |
| Frontmatter `slug` 和 提示块 `id`    | 保留路由和链接所用的内部标识符        |
| `Callout`、属性名以及 `type="warning"` | 保留组件约定                 |
| 导入路径                             | 保持不变，除非已配置的本地化规则会重写该路径 |

代码块内部同样如此：说明性注释可以翻译，命令和内部标识符则保持不变。将翻译后的文件与源文件对比时，
应允许代码块内的注释措辞有所不同，而不必要求每个代码块都逐字节一致。请通过文档站点的构建流程编译结果
(导入的组件及其属性均在其中定义) ，并在每个区域设置下检查渲染后的 提示块 及其锚点。单独的
MDX 语法检查无法解析站点的组件或路由。

## 要点总结

* 翻译完整的句子以及选定的显示文本字段，包括 alt 文本、frontmatter 值和相关属性。保留技术语法和标识符；URL 仅通过已配置的映射进行重写。
* 法语中的 `" : "` 标点可能会破坏未加引号的 YAML frontmatter，而 `{#id}` 标题后缀会导致普通 MDX 解析器解析失败。
* Google 的文档翻译不支持 Markdown；DeepL 将 `.md` 标为测试版支持，且未列出 MDX。
* remark 示例虽然能暴露文本节点，但完整的流水线还必须保留句子上下文，并处理这些节点之外的显示文本。
* General Translation 的 CLI 在翻译 `md` 和 `mdx` 文件时会保留语法，并在后续运行中复用匹配的译文。

## Related questions

- [如何翻译 i18n JSON 文件？](https://generaltranslation.com/zh/kb/translate-json-files.mdx): 只翻译 JSON 区域设置文件中的字符串值。非复数键、{{name}} 之类的占位符以及标签都应保持不变，但复数键会因语言而异：例如波兰语需要 inbox_few 和 inbox_many。请使用能识别文件格式的工具或 API，然后先解析并验证输出，再进行审校。
- [如何翻译 YAML 区域设置文件？](https://generaltranslation.com/zh/kb/translate-yaml-files.mdx): 只翻译字符串值，键、占位符（如 %{name} 或 {{name}}）和锚点均保持不变。包含冒号或以 % 或 { 开头的值需加引号；为每个文件设置区域设置根键或文件名，并补充目标语言所需的复数键。General Translation 的 CLI 会原地翻译 YAML 值，不会改动键。
- [如何让网站支持多语言？](https://generaltranslation.com/zh/kb/make-website-multilingual.mdx): 先确定译文放在哪里：代理、CMS 插件、建站工具，还是你自己的代码；然后按照 Google 的建议，为每种语言分配独立的 URL。完整翻译页面以及标题和元描述，用 hreflang 关联各语言版本，并提供语言切换器，而不是自动重定向访问者。
- [Google Translate 替代方案：General Translation 与 Google Translate 对比](https://generaltranslation.com/zh/kb/general-translation-vs-google-translate.mdx): Google Translate 适合快速翻译一次性文本，但要以另一种语言发布产品，还需要结合上下文翻译每个字符串、保持术语一致、正确处理变量和复数形式、进行审校，并建立发布流程。General Translation 能理解代码中每个字符串的上下文，将从代码、审校到每一次发布的整个本地化工作流全面自动化。
- [Crowdin 替代方案：General Translation 与 Crowdin 对比](https://generaltranslation.com/zh/kb/general-translation-vs-crowdin.mdx): 如果你希望将文案保留在组件中，并随构建生成译文，请选择 General Translation。Crowdin 围绕资源文件、译者和审校工作流程来管理翻译项目，需要工程师将其接入应用，并随产品迭代持续维护。对于开源社区翻译和由供应商主导的翻译项目，Crowdin 依然是很好的选择。

## Previous and next questions

- Previous question: [如何在不破坏时间轴的情况下翻译 SRT 字幕？](https://generaltranslation.com/zh/kb/translate-srt-subtitles.mdx)
- Next question: [如何找出未翻译的硬编码字符串？](https://generaltranslation.com/zh/kb/find-hardcoded-strings.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/zh/kb/sitemap.md) for every article.
