Loving Tina? us on GitHub0.0k

文档

学习

v.Latest
Documentation
国际化
目录

使用TinaCMS进行国际化

管理多语言内容对于全球覆盖至关重要。TinaCMS提供了多种灵活的选项来促进这一点。本指南重点介绍两种主要策略:

  • 基于目录的本地化
  • 基于字段的本地化

基于目录的本地化

使用基于目录的本地化时,您的内容应以目录为基础进行结构化,其中语言环境(例如,en,fr)位于集合根目录(例如,blog,docs)下。例如:

.
├── /blog/
│ ├── /en/
│ │ └── hello-world.md
│ └── /fr/
│ └── hello-world.md
└── /docs/
├── /en/
│ └── my-doc.md
└── /fr/
└── my-doc.md
实现基于目录的本地化的步骤

在您的config.ts中,您可能会有一个包含所有语言环境的集合

export const config = {
collections: [
{
label: 'Blog',
name: 'blog',
path: 'content/blog',
// ...其他设置
},
}
路由和文件结构:

无论您使用的是Next.js还是其他框架,您的路由逻辑都应更新,以根据URL或用户设置选择正确的语言环境。

// 示例:在NextJS中获取页面列表
const getStaticPaths = async({ locales }) {
// ...
})

使用语言环境,您可以根据路径筛选文档

// /pages/post/[filename].tsx
// `locale`与`params`一起提供
const getStaticProps = async({ params, locale }) {
const tinaProps = await client.BlogPostQuery({
// 组合`relativePath`,其中`locale`是`post`的子文件夹
relativePath: `${locale}/${params.filename}.mdx`,
});
return {
props: {
...tinaProps
}
}
}
有关设置NextJS特定实现路由的更多信息,请参阅我们的指南
内容管理

通过此设置,编辑者将通过文档列表浏览每个集合的语言环境。

本地化列表

如果用户想要创建现有文档的新本地化版本,他们可以从文档列表中点击“复制文档”,并在新文档的文件名中添加所需的语言环境。

基于字段的本地化

在这种方法中,每个本地化字段包含多个语言的嵌套值。例如,单个Markdown文件可能如下所示:

{
"title": {
"en": "Hello",
"fr": "Bonjour"
}
}
实现基于字段的本地化的步骤

您需要修改您的TinaCMS架构以包含本地化字段。

export const pageSchema = {
label: 'Page',
name: 'page',
fields: [
{
label: 'Title',
name: 'title',
type: 'object',
fields: [
{
type: 'string',
name: 'en',
label: 'English',
},
{
type: 'string',
name: 'fr',
label: 'French',
},
],
},
// ...其他字段
],
};
注意:如果您使用的是markdown/mdx内容,并希望使用markdown正文作为您的内容,您可能更倾向于使用基于目录的本地化方法。
显示本地化内容:

在您网站的组件中,您可以根据当前语言环境选择正确的本地化字段进行显示。

const PageComponent = ({ data, locale }) => {
const title = data.title[locale];
// ...显示内容
};
内容管理:

TinaCMS将所有本地化字段显示为根级字段的子字段。

本地化字段

使用GitHub Action进行国际化

使用基于目录的本地化时,开发人员需要将相应语言的MDX或JSON文件放置在正确的位置以加载多语言路由。开发人员可以选择手动翻译文本内容并将其放置在正确的位置,或者他们可以使用GitHub Action来自动化此过程。以下是一个解释有效GitHub Action工作流程的示例:

自动翻译工作流程

为GitHub Actions设置触发条件

必须为此GitHub Action设置触发条件。通常,触发发生在PR成功合并时。为了减少令牌消耗,计划触发是一个替代方案。下面的示例显示了一个仅在PR合并并包含指定目录中的更改时激活的GitHub Action。

# 仅在PR成功关闭并包含指定目录中的更改后触发
on:
pull_request:
types: [closed]
paths:
- 'content/docs/**.mdx'
jobs:
translate-mdx:
if: github.event.pull_request.merged == true

识别修改的目标文件

为了最小化令牌使用,仅识别修改的文件进行翻译是必要的。下面是一个列出所有修改文件的简单示例。

// 识别当前PR下的修改目标文件
async function getChangedFilesFromApi() {
try {
const response = await axios.get(
`https://api.github.com/repos/${OWNER}/${REPO_NAME}/pulls/${PR_NUMBER}/files`,
{
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json',
},
}
);
const mdxFiles = response.data
.filter(
(file) =>
file.filename.startsWith('content/docs/') &&
file.filename.endsWith('.mdx')
)
.map((file) => file.filename);
return mdxFiles;
} catch (error) {
console.error('从API获取更改文件时出错:', error.message);
return [];
}
}

创建翻译分支

创建一个单独的分支以区分原始分支和新添加的翻译是必要的。这种方法有助于手动审核。

# 为翻译文件创建一个单独的分支
- name: Create translation branch
if: env.HAS_CHANGED_FILES == 'true'
run: |
TIMESTAMP=$(date +%s)
PR_NUMBER="${{ github.event.pull_request.number }}"
BRANCH_NAME="translate-pr-$PR_NUMBER-$TIMESTAMP"
git checkout -b $BRANCH_NAME
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV

通过LLM API调用获取翻译

外部LLM用于自动翻译。翻译质量和格式完整性取决于所选模型和提示。下面是一个将MDX文件翻译成中文的英文提示示例,同时保留文档接口和关键信息。

Please translate the following Markdown content into Chinese, preserving all Markdown formatting, code blocks, and front matter metadata.Only translate the text content, do not modify code, variable names, or other technical content.Do not add ```markdown``` in the newly translated Markdown file.Please note the following special requirements:
1. Do not modify URLs, next and preview fields
2. Maintain the original format structure, including heading hierarchy, lists, tables, etc.
3. Comments in code blocks can be translated, but the code itself and its functionality should not be changed
4. Please return the translated markdown source code directly in your reply, without adding any other prompts or explanations
{{content}}

将所有更改提交到新分支并创建PR

由LLM生成的内容不能被视为完全可靠。将所有更改提交到新的PR以进行彻底验证代表了一种更谨慎和系统的方法。

const prTitle = `Chinese translation for PR #${PR_NUMBER}`;
const prBody = `This PR contains Chinese translations for the documentation files updated in PR (${SERVER_URL}/${REPO}/pull/${PR_NUMBER}).`;
const response = await axios.post(
`https://api.github.com/repos/${OWNER}/${REPO_NAME}/pulls`,
{
title: prTitle,
body: prBody,
head: BRANCH_NAME,
base: 'main',
},
{
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json',
},
}
);
上次编辑: July 11, 2025