mcpField
G
github-action

github-action

github.com/crowdin云与 DevOps944 次安装3 天前更新
代码仓库

关于 github-action

Crowdin GitHub Action 在 Docker 化的 GitHub Actions 步骤中运行 Crowdin CLI,同步源文件和翻译。它可将下载内容提交到本地化分支并创建拉取请求,并通过输入项控制各个流程阶段。

主要功能

  1. 01上传源文件和翻译
  2. 02下载源文件、翻译或 bundle
  3. 03提交并推送本地化分支
  4. 04按需创建拉取请求
  5. 05通过 command 运行 CLI 命令

适用场景

  1. 01代码推送时将源文件同步到 Crowdin
  2. 02定期下载翻译并提交拉取请求
  3. 03在工作流中检查翻译状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/crowdin/skills --skill github-action

安装后在 Claude Code 中输入/github-action确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
inputs.md
recipes.md

详细介绍

Crowdin GitHub Action

crowdin/github-action 在 Docker 容器中运行 Crowdin CLI,作为一个工作流步骤:它会将源文件上传到 Crowdin,下载已完成的翻译,将其提交到本地化分支,并创建拉取请求。

由于这是一个 Docker Action,因此只能在 Linux 运行器上运行——ubuntu-latest,或已安装 Docker 的自托管 Linux 运行器。它无法在 macos-* 或 windows-* 上运行。

参考:README · 示例 · 输入和输出 · 工作流配置示例

这个步骤是一条流水线,而不是一条命令

一个步骤最多执行五项操作,始终按以下固定顺序进行,每项操作都由各自的输入控制:

顺序输入执行操作
1upload_sources: true (默认值)crowdin upload sources
2upload_translations: truecrowdin upload translations
3download_sources: truecrowdin download sources,然后执行 git 部分
4download_translations: truecrowdin download,然后执行 git 部分
5download_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 有效并不代表大功告成。此操作会在运行时因凭据、文件模式和权限出错,因此只有当一次运行打印出预期阶段,而不是仅仅写好文件时,工作才算完成:

  1. 设置 dryrun_action: true 并手动触发工作流。CLI 会打印它将处理的文件,因此错误的 source 模式会在任何内容传到 Crowdin 之前显现出来。
  2. 移除该标记,再次手动触发,并将日志读到末尾:UPLOAD SOURCES,然后是 DOWNLOAD TRANSLATIONS,最后是 PR URL 或 NOTHING TO COMMIT。
  3. 对运行异常的工作流重新运行,并启用 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.ymlaction 会在仓库根目录中查找设置 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 过滤器

评论

支持 Markdown