关于 github-action
Crowdin GitHub Action 在 Docker 化的 GitHub Actions 步骤中运行 Crowdin CLI,同步源文件和翻译。它可将下载内容提交到本地化分支并创建拉取请求,并通过输入项控制各个流程阶段。
主要功能
- 01上传源文件和翻译
- 02下载源文件、翻译或 bundle
- 03提交并推送本地化分支
- 04按需创建拉取请求
- 05通过 command 运行 CLI 命令
适用场景
- 01代码推送时将源文件同步到 Crowdin
- 02定期下载翻译并提交拉取请求
- 03在工作流中检查翻译状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ crowdin/ skills --skill github-action安装后在 Claude Code 中输入/github-action确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/inputs.mdrecipes.md详细介绍
Crowdin GitHub Action
crowdin/github-action 在 Docker 容器中运行 Crowdin CLI,作为一个工作流步骤:它会将源文件上传到 Crowdin,下载已完成的翻译,将其提交到本地化分支,并创建拉取请求。
由于这是一个 Docker Action,因此只能在 Linux 运行器上运行——ubuntu-latest,或已安装 Docker 的自托管 Linux 运行器。它无法在 macos-* 或 windows-* 上运行。
参考:README · 示例 · 输入和输出 · 工作流配置示例
这个步骤是一条流水线,而不是一条命令
一个步骤最多执行五项操作,始终按以下固定顺序进行,每项操作都由各自的输入控制:
| 顺序 | 输入 | 执行操作 |
|---|---|---|
| 1 | upload_sources: true (默认值) | crowdin upload sources |
| 2 | upload_translations: true | crowdin upload translations |
| 3 | download_sources: true | crowdin download sources,然后执行 git 部分 |
| 4 | download_translations: true | crowdin download,然后执行 git 部分 |
| 5 | download_bundle: <id> | crowdin bundle download <id>,然后执行 git 部分 |
git 部分是一个整体操作:git add .、提交、强制推送本地化分支、创建 PR。各部分可以单独开关(push_translations、push_sources、create_pull_request),且只有第 3–5 行的操作会触发它。
这一执行顺序解释了该 Action 几乎所有令人意外的行为:
upload_sources默认为true。 如果你打算只下载,那么这一步也会将源文件推送到 Crowdin,除非你设置upload_sources: false。请明确设置所有关心的标志,不要依赖默认值。- 只有下载后才会执行 git 部分。 在仅上传的步骤中设置
create_pull_request: true不会生效——没有可提交的内容。 - 在一个步骤中执行两次下载,git 部分也会执行两次——向同一本地化分支提交两次,并由同一个 PR 包含。
- git 部分使用
git add .提交——工作区中所有有改动的内容都会被纳入,包括前面步骤生成的文件。请将 Crowdin 步骤放在所有构建步骤之前,或为它单独设置一个作业。 - 每次运行有改动时都会强制推送,因此未关闭的翻译 PR 会被重写,而不是追加提交——这就是为什么它的检查每次都会重新开始。
设置
五个步骤中有两个需要人工操作:第 2 步的仓库机密和第 4 步的拉取请求设置,都需要有仓库管理员权限的人在 GitHub 界面中完成。请明确地把这份清单交给对方,而不要假设这些设置已经完成——即使工作流文件本身完全正确,缺少这些设置也会导致首次运行失败。
1. 配置 crowdin.yml
该 Action 使用与 CLI 相同的 crowdin.yml——crowdin-cli 技能介绍了 files、占位符和语言映射。这里有三个部分尤为重要:
"project_id_env": "CROWDIN_PROJECT_ID"
"api_token_env": "CROWDIN_PERSONAL_TOKEN"
"preserve_hierarchy": true
files:
- source: "/src/locales/en/**/*.json"
translation: "/src/locales/%two_letters_code%/**/%original_file_name%"
project_id_env/api_token_env指向工作流提供的环境变量,因此凭据不会被提交。preserve_hierarchy: true会使 Crowdin 的文件树与仓库保持一致。如果不设置,Crowdin 会移除共同的父目录,下载的翻译就会落在与仓库路径不匹配的位置——这是 PR 中大量文件出现在错误位置的常见原因。从原生 GitHub(OAuth)集成迁移时,也必须设置此项。- 将文件放在仓库根目录,或通过
config输入传递其路径(开头不要加/)。
如果仓库只有一种源文件和翻译文件的模式,可以完全省略该文件,改为通过输入传递 source 和 translation——请参阅不使用 crowdin.yml。二者只能选其一:如果仓库中存在 crowdin.yml,它会与这些输入冲突。
2. 创建仓库机密
在 Settings → Secrets and variables → Actions 中添加:
CROWDIN_PROJECT_ID— 数字项目 ID,可在 Crowdin 项目中的 Tools → API 找到。CROWDIN_PERSONAL_TOKEN— Crowdin 个人访问令牌(crowdin.com,或 Enterprise 中的 Account Settings → Access Tokens)。
根据工作流的实际操作范围设置令牌权限——对于常规同步,需要 Projects → Read、Translation Status → Read、Source files & strings → Read and Write、Translations → Read and Write。
3. 编写工作流
.github/workflows/crowdin.yml:
name: Crowdin
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
concurrency:
group: crowdin
cancel-in-progress: false
jobs:
synchronize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Synchronize with Crowdin
uses: crowdin/github-action@v3
with:
upload_sources: true
upload_translations: false
download_translations: true
localization_branch_name: l10n_crowdin
create_pull_request: true
pull_request_title: 'New Crowdin translations'
pull_request_base_branch_name: main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
修改时值得保留的细节:
- 凭据放在
env:中,而不是with:中——CLI 和操作的 git 代码会从环境中读取它们。(token和project_id输入可作为替代方案,但放在with:中的令牌会显示在步骤渲染后的输入中。) workflow_dispatch让你无需等待推送即可测试工作流。- 配置
concurrency并设置cancel-in-progress: false,可以让运行排队,而不是互相争抢。如果 Crowdin 仍在构建上一次导出时开始第二次运行,就会失败并返回 409。 - 值得明确设置
pull_request_base_branch_name:若未设置,基础分支就是触发运行的 ref;对于推送到main的情况,这样是正确的,但用于标签和发布触发器时则会出错。 - 使用单个同步步骤是最简单的结构,但两个方向各有适合的节奏——每次推送到
main时上传,按计划下载。参见拆分工作流。 actions/checkout@v7是 2026 年 8 月的当前版本;请查看其发布版本,不要直接照搬较早示例中的固定版本。
4. 授予令牌写入权限
推送分支并创建 PR 需要 contents: write 和 pull-requests: write。使用默认的 GITHUB_TOKEN 时,这意味着既要设置上方作业级别的 permissions: 块,也要启用仓库设置 Settings → Actions → General → Allow GitHub Actions to create and approve pull requests。如果未启用此设置,即使权限看起来正确,创建 PR 仍会失败。
默认令牌有一项无法通过权限设置解决的限制:它创建的拉取请求不会触发工作流,因此翻译 PR 不会运行 CI 检查。如果必须在该 PR 上运行检查,请使用非 Actions bot 的身份验证方式——GitHub App(权限范围明确、自动轮换,是更好的默认选择),或设置 repo 范围的经典 PAT,并将其作为 GH_TOKEN 或 GITHUB_TOKEN 传入。
5. 验证其正常运行
YAML 有效并不代表大功告成。此操作会在运行时因凭据、文件模式和权限出错,因此只有当一次运行打印出预期阶段,而不是仅仅写好文件时,工作才算完成:
- 设置
dryrun_action: true并手动触发工作流。CLI 会打印它将处理的文件,因此错误的source模式会在任何内容传到 Crowdin 之前显现出来。 - 移除该标记,再次手动触发,并将日志读到末尾:
UPLOAD SOURCES,然后是DOWNLOAD TRANSLATIONS,最后是 PR URL 或NOTHING TO COMMIT。 - 对运行异常的工作流重新运行,并启用 Enable debug logging——该操作会检测
RUNNER_DEBUG,转储其环境,并在每次 CLI 调用时添加--verbose --debug。
触发运行需要持有机密的人员操作;请让对方提供运行日志,不要只检查工作流文件。
哪些情况会出问题,以及原因
先查看步骤日志:日志会依次打印 UPLOAD SOURCES、DOWNLOAD TRANSLATIONS、PUSH TO BRANCH、NOTHING TO COMMIT 和 CREATE PULL REQUEST,因此无需猜测,就能看出哪个流水线阶段失败了。
| 症状 | 原因 | 修复方法 |
|---|---|---|
运行成功,没有 PR,日志显示 NOTHING TO COMMIT | 下载的翻译与已提交的内容逐字节相同 | 这是预期行为——无需处理 |
| 运行成功,没有 PR,日志中也没有下载记录 | download_translations 保持了默认值 false | 设置 download_translations: true |
ERROR: Either 'GITHUB_TOKEN' or 'GH_TOKEN' must be set | 步骤的 env: 中缺少令牌 | 添加 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
FAILED TO AUTHENTICATE WITH GITHUB,或推送时出现 403 | 作业缺少写入权限,或仓库禁止 Actions 创建 PR | 添加 permissions: 块,并且启用仓库设置(第 4 步) |
| PR 已创建,但没有 CI 检查运行 | 使用默认 GITHUB_TOKEN 创建的 PR 不会触发工作流 | 使用 GitHub App 令牌或 PAT |
| 每次同步运行时,检查都会重新启动 | 每次都会强制推送本地化分支 | 将 PAT 传给 actions/checkout,让推送由用户发起 |
| 由标签或发布触发时,创建 PR 失败 | 基础分支默认为触发引用,即 refs/tags/... | 设置 pull_request_base_branch_name |
| 后续步骤访问已下载文件时出现权限错误 | 容器以 root 身份运行,因此写入的文件归 root 所有 | 添加 user: auto,以检测工作区所有者 |
出现 409 / 构建已在进行中 | 针对同一个 Crowdin 项目的运行并行执行 | 使用 concurrency 序列化运行,或在矩阵中设置 max-parallel: 1 |
| 翻译 PR 中包含构建产物 | git add . 会提交整个工作区 | 将 Crowdin 步骤移到构建之前,或放入单独的作业 |
| 没有下载内容,项目基于字符串 | download_translations 不适用于基于字符串的项目 | 下载一个 bundle:download_bundle: <id> |
未找到 crowdin.yml | action 会在仓库根目录中查找 | 设置 config: path/to/crowdin.yml,开头不要加 / |
| 企业版:CLI 返回 404 或身份验证失败 | 企业版需要组织专属的 API 主机 | 设置 base_url: 'https://{organization}.api.crowdin.com' |
command — 运行任意 CLI 命令
command(以及可选的 command_args)会将步骤转换为任意 CLI 调用:status、auto-translate、bundle、string,以及 CLI 支持的任何命令。
- name: Fail the build unless translations are complete
uses: crowdin/github-action@v3
with:
command: 'status translation'
command_args: '--fail-if-incomplete'
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
其实现方式会带来两个后果,但上游文档都没有说明:
command会替换整个流水线。 该步骤运行命令后就会退出——无论其他输入如何设置,都不会上传、下载、提交或创建 PR。要在上传和下载之间运行命令,必须拆分为三个独立步骤(AI 预翻译是典型示例)。- action 的配置输入不会传递给它。
config、token、project_id、base_url、base_path、crowdin_branch_name和dryrun_action不会转发给command步骤,只有command_args会传递。请通过env:提供凭据,并将其他内容放入command_args(--config path/to/crowdin.yml、--branch main、--dryrun)。
该命令的标准输出可供后续步骤通过 command_output 输出使用。
应固定到哪个版本
@v3 是当前稳定版本线,运行 Crowdin CLI 5。
@v2 是旧版,内置基于 Java 的 Crowdin CLI 4。两者的每个输入、输出和默认值都完全相同,因此升级流水线式步骤只需修改一行版本固定值;变化的是底层 CLI,因此传给 command 和 *_args 的字符串也会随之变化。最值得注意的是,v4 的 pre-translate 改为 auto-translate,--plain 改为 -o plain;其余变更请参阅迁移参考。只有当 command 步骤仍依赖 v4 专属的 CLI 语法时,才继续使用 @v2。
相关技能
- crowdin-cli —
crowdin.yml配置,以及每个输入对应的命令和标志 - crowdin-api-client — 用于 CLI 无法覆盖的自动化
- croql — 用于字符串命令
command_args的 CroQL 过滤器