Última atividade 1 month ago

翻译文档为中文文档

Revisão c84b1ab9448ac27957da3df74e3769d03e22123c

.gitignore Bruto
1# Python
2.venv/
3
4build/
5docsite/
6translated/
7tmp/
8
9**.log
10**.txt
11!commit.txt
12
13aitr.toml
14config.toml
15
DOCS.md Bruto

中文文档

本文档使用 AI 翻译

项目流程

首次使用

  1. 创建空分支
git switch --orphan docs
  1. 首次提交
git add README.md
git commit -am init
git push origin docs
  1. 拉取上游源码
mkdir -p docsite
git remote add upstream https://github.com/xxx/docs.git
git reset --hard
git fetch upstream main
git merge upstream/main
git rev-parse --short HEAD > ../commit.txt
popd
  1. 复制源文档
rm -rf docs
# cp -r docsite/docs .
cp -r docsite/content .
mv content docs    
  1. 全量翻译
aitr
  1. 本地测试与构建
git clone https://github.com/xxx/docs.git docsite
cp -r docs_zh/* ./docsite/content
cd docsite
  1. 启动或构建
# NodeJS
npm install
npm run dev

# Hugo
hugo server

...

2. AI 翻译

  • 安装 CLI 工具 (增量更新直接使用 AI CLI 工具直接对比)
curl -L https://fx4.cn/aitr | bash
  1. 设置环境变量 config.toml
...
[[providers]]
enabled = true
name = "grok"
api_key = "xxx"
base_url = "https://api.x.ai/v1"
model = "grok-3"
concurrency = 1 # 线程数
rate_delay = 3.0 # 每个请求后等待 1.0 秒(可根据限流调整)
  1. AI 翻译
aitr
README.md Bruto

教程

本项目使用的教程

初始化项目

  1. 创建空分支
# 新项目
git init
git branch -m docs
# 已存在的项目,创建空分支
git switch --orphan docs
  1. 将本项目的文件下载至创建的翻译项目
curl -fsSL https://fx4.cn/gendocs | bash
  1. 更新上游项目链接
GIT_DOCS=含.git结尾的项目地址
sed -i "s#https://github.com/xxx/docs.git#${GIT_DOCS}#g" *.*
sed -i "s#https://github.com/xxx/docs.git#${GIT_DOCS}#g" .github/workflows/docs.yml
  1. 设置项目地址
# 新项目
git remote add origin <https 或 git 地址>
# 已存在的项目
git remote set-url origin <https 或 git 地址>
config.example.toml Bruto
1# 根目录 - 包含需要翻译的 Markdown 文件
2root_dir = "./docs"
3
4# 输出目录 - 翻译后的文件保存位置
5output_dir = "./docs_zh"
6
7# 输出模式: "overwrite" (覆盖原文件) 或 "new_folder" (保存到新文件夹)
8output_mode = "new_folder"
9
10# 排除的目录 (逗号分隔)
11exclude_dir = "node_modules,.git,_build"
12
13# 最大 token 数
14max_tokens = 99999
15
16# 大文件拆分阈值 (单位:字符)
17max_chunk_size = 8192
18
19# 系统提示词(支持多行,使用 """ 包裹)
20system_prompt = """
21你是一个专业的技术文档翻译专家。请将以下英文 Markdown 文档翻译成流畅、自然的简体中文。
22
23严格要求:
241. 保留完整的 Markdown 格式,包括标题、列表、表格、代码块、链接、图片等一切结构完全不变。
252. 代码块、命令行、文件名、路径、API 名称、配置文件内容、技术术语等保持原样(不要翻译)。
263. 专有名词(如产品名、框架名、软件名,例如 Traefik、Docker、Kubernetes)保持英文原名。
274. Hugo 短代码和模板语法(如 {{< xxx >}}、{{ xxx }}、{{</ xxx >}} 等所有以 {{ 或 {{< 开头的标签)必须完整保留原样,不翻译、不修改其内部任何内容。
285. 对于 YAML frontmatter(文档开头的 --- 之间的内容):
29 - 只翻译实际需要本地化的字符串值内容(如 title、description、linkTitle 等字段的值)。
30 - tags 字段的值(通常为字符串或字符串列表)必须完全保持原英文不变,不进行任何翻译或修改。
31 - 其他字段(如 keywords 等)按正常规则处理:如果为字符串值则翻译(如 description),如果为列表则视情况保留英文(专有名词不翻译)。
32 - 严格保留原文档中的所有字段、键名、结构、格式、缩进和所有机制(包括已有的 YAML 锚点 &xxx 和别名 *xxx)。
33 - 如果原文档中已有锚点定义,则在翻译该锚点对应的字符串值时保留锚点标记(如 &desc);别名引用(如 *desc)保持原样不变。
34 - 如果原文档中没有锚点或别名,则翻译后绝对不得新增任何锚点、别名、params 块或其他额外字段。
35 - 绝对不得添加、删除或修改任何原有字段、锚点、别名或 params 等结构,仅对需要本地化的字符串值进行翻译。
36 - aliases、keywords、tags 等列表字段的值,按原文档格式保留(保持原有引号使用情况,不统一添加或移除引号)。
37 - 必须输出且仅输出一次完整的 YAML Front Matter(以 --- 开头,以 --- 结尾)。
38 - 结尾的 --- 必须独占一行,且在其后必须紧跟一个空行。
39 - 绝对不要在翻译后的 Front Matter 之前或之后保留原始的英文 Front Matter。
406. 翻译要准确、专业、易懂,技术术语使用业界通用中文表达。
417. 绝对禁止在文档开头或 YAML frontmatter 前后添加任何 Markdown 代码块标记(如 ```markdown 或 ```),保持文档结构的纯净。
428. 绝对禁止自作主张地添加任何原文档中不存在的内容,包括但不限于:完整的语言指南、示例代码、学习资源、最佳实践等。只翻译原文档中已有的内容,不多不少。
439. 只输出翻译后的完整 Markdown 内容,不要添加任何说明、注释或多余文本。
4410. Markdown 链接 `[text](url)` 中的 `url` 必须完全保持原样,绝对不要修改、翻译或移除路径中的任何部分。即使是相对路径或绝对路径,也都必须保持原样。
45"""
46
47[[providers]]
48name = "grok"
49api_key = "xxx"
50base_url = "https://api.x.ai/v1"
51model = "grok-3"
52concurrency = 4 # 线程数
53rate_delay = 3.0 # 每个请求后等待 1.0 秒(可根据限流调整)
deploy.sh Bruto
1#!/usr/bin/env bash
2
3#============================================================
4# File: deploy.sh
5# Description: 部署中文文档
6# URL:
7# Author: Jetsung Chan <[email protected]>
8# Version: 0.2.0
9# CreatedAt: 2025-12-16
10# UpdatedAt: 2026-01-27
11#============================================================
12
13
14if [[ -n "${DEBUG:-}" ]]; then
15 set -eux
16else
17 set -euo pipefail
18fi
19
20DEFAULT_BRANCH="${BRANCH:-main}"
21HUGO_VERSION=${HUGO:-0.154.2}
22
23DELETE_FILE="deleted_docs.txt"
24ADD_FILE="new_docs.txt"
25MODIFIED_FILE="modified_docs.txt"
26TRANSLATE_LIST="translate_list.txt"
27
28UPSTREAM_URL="${UPSTREAM_URL:-}"
29UPSTREAM_NAME="upstream"
30
31# 命令行参数
32CUSTOM_BRANCH=""
33CUSTOM_UPSTREAM=""
34
35install_hugo() {
36 echo "======================================"
37 echo "📦 开始安装 Hugo"
38 echo "======================================"
39 echo "→ 目标版本: $HUGO_VERSION"
40 echo "→ 正在下载并安装..."
41 curl -L https://fx4.cn/hugo | bash -s -- -v "$HUGO_VERSION" -w
42 echo "✓ Hugo 安装完成"
43 hugo version
44 echo "======================================"
45}
46
47setup_config() {
48 echo "======================================"
49 echo "⚙️ 开始设置配置文件"
50 echo "======================================"
51 if [[ -f config.example.toml ]]; then
52 echo "→ 从 config.example.toml 提取基础配置..."
53 sed '/providers/,$d' ./config.example.toml | tee config.toml > /dev/null
54 echo "✓ 基础配置提取完成"
55 else
56 echo "⚠️ config.example.toml 不存在,跳过基础配置"
57 fi
58
59 if [[ -f aitr.toml ]]; then
60 echo "→ 从 aitr.toml 追加日志配置..."
61 sed -n '/logging/,$p' aitr.toml | tee -a config.toml > /dev/null
62 echo "✓ 日志配置追加完成"
63 else
64 echo "⚠️ aitr.toml 不存在,跳过日志配置"
65 fi
66 echo "✓ 配置文件设置完成"
67 echo "======================================"
68}
69
70sync_source() {
71 echo "======================================"
72 echo "📚 开始同步源文档"
73 echo "======================================"
74 echo "→ 准备工作目录..."
75 [[ -d docsite ]] || mkdir docsite
76
77 pushd docsite > /dev/null
78 if [[ ! -d .git ]]; then
79 echo "→ 初始化 git 仓库..."
80 git init
81 echo "→ 添加 upstream remote: ${UPSTREAM_URL}"
82 git remote add "${UPSTREAM_NAME}" "${UPSTREAM_URL}"
83 else
84 # 检查是否已经存在 upstream
85 if ! git remote get-url "${UPSTREAM_NAME}" >/dev/null 2>&1; then
86 echo "→ 添加 upstream remote..."
87 git remote add "${UPSTREAM_NAME}" "${UPSTREAM_URL}"
88 else
89 current_url=$(git remote get-url "${UPSTREAM_NAME}")
90 if [[ "${current_url}" != "${UPSTREAM_URL}" ]]; then
91 echo "→ 更新 upstream URL"
92 echo " 旧 URL: ${current_url}"
93 echo " 新 URL: ${UPSTREAM_URL}"
94 git remote set-url "${UPSTREAM_NAME}" "${UPSTREAM_URL}"
95 fi
96 fi
97 fi
98 echo "→ 正在拉取最新代码..."
99 echo " 分支: $DEFAULT_BRANCH"
100 echo " Remote: ${UPSTREAM_NAME}"
101 git reset --hard
102 git fetch "${UPSTREAM_NAME}" "${DEFAULT_BRANCH}"
103 git merge "${UPSTREAM_NAME}"/"${DEFAULT_BRANCH}"
104 COMMIT_SHA=$(git rev-parse --short HEAD)
105 echo "$COMMIT_SHA" > ../commit.txt
106 echo "✓ 代码同步完成 (commit: $COMMIT_SHA)"
107 popd > /dev/null
108
109 echo "→ 清理旧文档目录..."
110 rm -rf docs
111 echo "→ 复制源文档..."
112 if [[ -d docsite/content ]]; then
113 cp -r docsite/content .
114 mv content docs
115 echo "✓ 已从 docsite/content 复制文档"
116 elif [[ -d docsite/docs ]]; then
117 cp -r docsite/docs .
118 echo "✓ 已从 docsite/docs 复制文档"
119 else
120 echo "❌ docsite 目录下没有 content 或 docs 目录,无法同步文档。" >&2
121 exit 1
122 fi
123 echo "✓ 源文档同步完成"
124 echo "======================================"
125}
126
127# 增量更新
128update_incremental() {
129 echo "======================================"
130 echo "🔄 开始增量更新流程"
131 echo "======================================"
132 if [[ -z "$UPSTREAM_URL" ]]; then
133 echo "❌ UPSTREAM_URL 未设置,无法进行增量更新。" >&2
134 exit 1
135 fi
136
137 echo "→ 步骤 1/6: 同步源文档"
138 sync_source
139
140 # 记录删除的文件
141 echo "→ 步骤 2/6: 检测已删除的文件"
142 echo " 正在扫描已删除的文档..."
143 git ls-files --deleted docs/ | tee "$DELETE_FILE"
144 ROOT_DIR=$(grep root_dir config.toml | cut -d'"' -f 2 | sed 's|^\./||')
145 export ROOT_DIR
146 OUTPUT_DIR=$(grep output_dir config.toml | cut -d'"' -f 2 | sed 's|^\./||')
147 export OUTPUT_DIR
148 echo " 根目录: $ROOT_DIR"
149 echo " 输出目录: $OUTPUT_DIR"
150 # sed -i "s|^$ROOT_DIR/|$OUTPUT_DIR/|g" "$DELETE_FILE"
151 # 删除对应的输出文件
152 echo " 正在清理对应的输出文件..."
153 while read -r file; do
154 new_file="${file/$ROOT_DIR/$OUTPUT_DIR}"
155 echo " 删除: $new_file"
156 rm -rf "$new_file" || true
157 done < "$DELETE_FILE"
158 echo "✓ 已清理删除的文件"
159
160 # 更新 git 索引
161 echo "→ 步骤 3/6: 更新 git 索引"
162 git add .
163 # 记录新增和修改的文件
164 echo " 正在检测新增的文件..."
165 git diff --cached --name-only --diff-filter=A docs/ | tee "$ADD_FILE"
166 echo " 正在检测修改的文件..."
167 git diff --cached --name-only --diff-filter=M docs/ | tee "$MODIFIED_FILE"
168
169 echo "→ 步骤 4/6: 生成待翻译文件列表"
170 cat "$ADD_FILE" "$MODIFIED_FILE" | tee "$TRANSLATE_LIST"
171
172 # 移除以 .png .jpg .jpeg .gif .svg 结尾的文件
173 echo " 过滤图片文件..."
174 sed -i '/\.\(png\|jpg\|jpeg\|gif\|svg\)$/d' "$TRANSLATE_LIST"
175 echo "✓ 已生成待翻译文件列表: $TRANSLATE_LIST"
176
177 echo "→ 步骤 5/6: 设置配置文件"
178 setup_config
179
180 # # 翻译增量文件
181 # if ! command -v aitr &> /dev/null; then
182 # echo "正在安装 aitr ..."
183 # curl -L https://fx4.cn/aitr | bash
184 # fi
185
186 # 调用 aitr 进行翻译
187 echo "→ 步骤 6/6: 执行翻译"
188 if command -v aitr &> /dev/null; then
189 echo " 正在调用 aitr 翻译文件..."
190 aitr --input "$TRANSLATE_LIST" --list --output translated
191 echo " 正在复制翻译结果到输出目录..."
192 cp -r "translated/${ROOT_DIR}/"* "${OUTPUT_DIR}"/
193 echo "✓ 翻译完成"
194 else
195 echo "⚠️ aitr 未安装,跳过翻译步骤。"
196 fi
197 echo "======================================"
198 echo "✓ 增量更新完成"
199 echo "======================================"
200}
201
202# 部署 docs_zh 到 docsite
203deploy_docs_zh() {
204 echo "======================================"
205 echo "📋 开始部署 docs_zh 到 docsite"
206 echo "======================================"
207 if [[ ! -d docsite ]]; then
208 if [[ -z "$UPSTREAM_URL" ]]; then
209 echo "❌ UPSTREAM_URL 未设置,无法克隆文档站点。" >&2
210 exit 1
211 fi
212 echo "→ docsite 目录不存在,正在克隆..."
213 git clone "$UPSTREAM_URL" docsite
214 echo "✓ 克隆完成"
215 fi
216
217 if [[ -d "translated/docs" ]]; then
218 echo "→ 检测到 translated/docs,正在覆盖 docs_zh..."
219 cp -r translated/docs/* docs_zh/
220 echo "✓ 已覆盖 docs_zh"
221 fi
222
223 if [[ ! -d docs_zh ]]; then
224 echo "❌ docs_zh 目录不存在,无法部署。" >&2
225 exit 1
226 fi
227
228 echo "→ 正在部署 docs_zh 到 docsite..."
229 if [[ -d docsite/content ]]; then
230 cp -r docs_zh/* ./docsite/content/
231 echo "✓ 已部署到 docsite/content/"
232 elif [[ -d docsite/docs ]]; then
233 cp -r docs_zh/* ./docsite/docs/
234 echo "✓ 已部署到 docsite/docs/"
235 else
236 echo "❌ docsite 目录下没有 content 或 docs 目录,无法部署。" >&2
237 exit 1
238 fi
239 echo "======================================"
240 echo "✓ 文档部署完成"
241 echo "======================================"
242}
243
244# 调用翻译脚本
245translate() {
246 echo "======================================"
247 echo "🌐 开始执行翻译"
248 echo "======================================"
249 if ! command -v aitr &> /dev/null; then
250 echo "❌ aitr 未安装,请先安装 aitr。" >&2
251 exit 1
252 fi
253 echo "→ 正在调用 aitr 翻译工具..."
254 aitr
255 echo "======================================"
256 echo "✓ 翻译完成"
257 echo "======================================"
258}
259
260usage() {
261 cat << EOF
262用法: $0 [选项]
263
264选项:
265 -d --deploy 部署 docs_zh 到 docsite
266 -c --config 设置配置文件
267 -s --sync 同步源文档
268 -u --update 增量更新(同步+翻译)
269 -t --translate 执行翻译
270 -b --branch 指定分支 (默认: main)
271 -U --upstream 指定上游 URL
272 -h --help 显示此帮助信息
273
274示例:
275 $0 --translate
276 $0 --update
277 $0 --sync --branch develop
278 $0 --update --upstream https://github.com/user/repo.git
279EOF
280}
281
282main() {
283 echo "======================================"
284 echo "🚀 部署脚本启动"
285 echo "======================================"
286
287 if [[ $# -eq 0 ]]; then
288 echo "❌ 未指定任何操作" >&2
289 usage
290 exit 1
291 fi
292
293 # 先解析所有参数
294 local actions=()
295 while [[ $# -gt 0 ]]; do
296 case $1 in
297 -b|--branch)
298 CUSTOM_BRANCH="$2"
299 shift 2
300 ;;
301 -U|--upstream)
302 CUSTOM_UPSTREAM="$2"
303 shift 2
304 ;;
305 -d|--deploy)
306 actions+=("deploy")
307 shift
308 ;;
309 -c|--config)
310 actions+=("config")
311 shift
312 ;;
313 -s|--sync)
314 actions+=("sync")
315 shift
316 ;;
317 -u|--update)
318 actions+=("update")
319 shift
320 ;;
321 -t|--translate)
322 actions+=("translate")
323 shift
324 ;;
325 --help|-h)
326 usage
327 exit 0
328 ;;
329 *)
330 echo "❌ 未知参数: $1" >&2
331 usage
332 exit 1
333 ;;
334 esac
335 done
336
337 # 应用自定义参数
338 if [[ -n "$CUSTOM_BRANCH" ]]; then
339 DEFAULT_BRANCH="$CUSTOM_BRANCH"
340 fi
341 if [[ -n "$CUSTOM_UPSTREAM" ]]; then
342 UPSTREAM_URL="$CUSTOM_UPSTREAM"
343 fi
344
345 echo "当前分支: $DEFAULT_BRANCH"
346 echo "Hugo 版本: $HUGO_VERSION"
347 if [[ -n "$UPSTREAM_URL" ]]; then
348 echo "Upstream URL: $UPSTREAM_URL"
349 else
350 echo "Upstream URL: (未设置)"
351 fi
352 echo "======================================"
353
354 # 执行操作
355 for action in "${actions[@]}"; do
356 case $action in
357 deploy)
358 echo "→ 执行操作: 部署 docs_zh"
359 deploy_docs_zh
360 ;;
361 config)
362 echo "→ 执行操作: 设置配置文件"
363 setup_config
364 ;;
365 sync)
366 echo "→ 执行操作: 同步源文档"
367 sync_source
368 ;;
369 update)
370 echo "→ 执行操作: 增量更新"
371 update_incremental
372 ;;
373 translate)
374 echo "→ 执行操作: 执行翻译"
375 translate
376 ;;
377 esac
378 done
379
380 echo "======================================"
381 echo "✓ 部署脚本执行完成"
382 echo "======================================"
383}
384
385main "$@"
docs.yml Bruto
1name: Documentation
2
3on:
4 push:
5 branches:
6 - docs
7 paths:
8 - 'docs_zh/**'
9 - '.github/workflows/docs.yml'
10 workflow_dispatch:
11
12permissions:
13 contents: write
14 pages: write
15 id-token: write
16
17concurrency:
18 group: pages
19 cancel-in-progress: false
20defaults:
21 run:
22 shell: bash
23
24jobs:
25 build:
26 env:
27 HUGO_VERSION: 0.154.2
28 TZ: Asia/Shanghai
29 runs-on: ubuntu-latest
30 steps:
31 - uses: actions/checkout@v6
32 - name: Install Hugo
33 run: |
34 curl -L https://fx4.cn/hugo | bash -s -- -v "$HUGO_VERSION" -w
35 - name: Verify installations
36 run: |
37 echo "Hugo: $(hugo version)"
38 echo "Node.js: $(node --version)"
39 - name: Fetch Source
40 run: |
41 git clone https://github.com/xxx/docs.git docsite
42 - name: Fix
43 run: |
44 # sed -i 's/refLinksErrorLevel: WARNING/refLinksErrorLevel: ERROR/' docsite/hugo.yaml
45 sed -i '/baseURL/d' docsite/hugo.yaml
46 - name: Build Docs
47 run: |
48 cp -r docs_zh/* ./docsite/content
49 cd docsite/
50 npm install
51 hugo build
52 - name: Copy CNAME
53 run: cp CNAME docsite/public/
54 - name: Upload build artifacts
55 uses: actions/upload-artifact@v6
56 with:
57 name: docs-site
58 path: docsite/public
59 retention-days: 1
60
61 deploy-github-pages:
62 environment:
63 name: github-pages
64 url: ${{ steps.deployment.outputs.page_url }}
65 needs: build
66 runs-on: ubuntu-latest
67 steps:
68 # - uses: actions/configure-pages@v5
69 - name: Download build artifacts
70 uses: actions/download-artifact@v6
71 with:
72 name: docs-site
73 path: ./public
74 - name: Deploy to Branch
75 uses: peaceiris/actions-gh-pages@v4
76 with:
77 github_token: ${{ secrets.GITHUB_TOKEN }}
78 publish_dir: ./public
79 # - uses: actions/upload-pages-artifact@v4
80 # with:
81 # path: docsite/public
82 # - uses: actions/deploy-pages@v4
83 # id: deployment
84
85 deploy-ssh-server:
86 needs: build
87 runs-on: ubuntu-latest
88 steps:
89 - name: Download build artifacts
90 uses: actions/download-artifact@v6
91 with:
92 name: docs-site
93 path: ./public
94 - name: Compress to tar.xz
95 run: |
96 tar -cJf docs-site.tar.xz public/
97 - name: Set up SSH
98 uses: LuisEnMarroquin/[email protected]
99 with:
100 ORIGIN: ${{ secrets.SSH_HOSTNAME }}
101 SSHKEY: ${{ secrets.SSH_KEY }}
102 NAME: webserver
103 PORT: ${{ secrets.SSH_PORT }}
104 USER: ${{ secrets.SSH_USERNAME }}
105 - run: echo "" >> ~/.ssh/access # fix
106 - name: Deploy the website
107 env:
108 WEBROOT: /data/wwwroot/docker
109 run: |
110 ssh webserver "rm -rf $WEBROOT && mkdir -p $WEBROOT"
111 scp docs-site.tar.xz webserver:${WEBROOT}/
112 ssh webserver "cd $WEBROOT && tar -xJf docs-site.tar.xz --strip-components=1 && rm -f docs-site.tar.xz"
init.sh Bruto
1#!/usr/bin/env bash
2
3if [[ -n "${DEBUG:-}" ]]; then
4 set -eux
5else
6 set -euo pipefail
7fi
8
9BASE_URL="https://gist.asfd.cn/jetsung/gendocs/raw/HEAD"
10
11download_files() {
12 curl -fsSL -O "${BASE_URL}/deploy.sh"
13 chmod +x deploy.sh
14
15 curl -fsSL -o README.md "${BASE_URL}/DOCS.md"
16
17 curl -fsSL -O "${BASE_URL}/config.example.toml"
18
19 curl -fsSL -O "${BASE_URL}/config.example.toml"
20
21 curl -fsSL -O "${BASE_URL}/.gitignore"
22
23 curl -fsSL --create-dirs -o ".github/workflows/docs.yml" "${BASE_URL}/docs.yml"
24}
25
26main() {
27 download_files
28
29 if [[ ! -f CNAME ]]; then
30 echo "" > CNAME
31 fi
32}
33
34main "$@"
35