# How the Co-op Translator GitHub Actions Automates Content Translation in ML-For-Beginners

> Discover how the Co-op Translator GitHub Actions automatically translates ML For Beginners content using Docker and the Microsoft Translator API. Learn about community contributions.

- Repository: [Microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners)
- Tags: internals
- Published: 2026-02-28

---

**The Co-op Translator is a GitHub Actions pipeline that automatically translates ML-For-Beginners educational content into multiple languages using Docker containers, the Microsoft Translator Text API, and community-reviewed pull requests.**

The **microsoft/ML-For-Beginners** repository maintains synchronized multilingual versions of its machine learning curriculum through this automated system. The Co-op Translator triggers on every push to the `main` branch or via scheduled cron jobs, processing Markdown files, Jupyter notebooks, and HTML content through a containerized Python engine.

## System Architecture and Components

The translation pipeline consists of three integrated components that handle orchestration, execution, and delivery.

### GitHub Actions Workflow Orchestration

The [`.github/workflows/co-op-translator.yml`](https://github.com/microsoft/ML-For-Beginners/blob/main/.github/workflows/co-op-translator.yml) file defines the automation triggers and job sequences. It configures the workflow to execute on `push` events to the `main` branch and on a nightly schedule using `cron` syntax, ensuring translations stay current with source material changes.

The workflow manages environment variables and secrets, specifically exposing the `AZURE_TRANSLATOR_KEY` stored as a repository secret and the `LANGUAGES` variable (formatted as `"es,fr,de,zh"`). These values are injected at runtime and automatically masked in job logs to prevent credential exposure.

### Docker Translation Engine

The core translation logic runs inside a container built from `docker/Dockerfile`. This image packages Python with required libraries including `requests` and `nbformat`, along with the [`scripts/translate.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/scripts/translate.py) script that implements the actual conversion logic.

Inside the container, [`translate.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/translate.py) performs the following operations:

- Scans the repository for `.ipynb`, `.md`, and `.html` files
- Extracts human-readable text while preserving code blocks and formatting
- Sends text in batches to the **Microsoft Translator Text API** endpoint (`https://api.cognitive.microsofttranslator.com/translate`)
- Reinserts translated strings into copies of the original files, maintaining notebook cell structure and Markdown syntax
- Writes output to a temporary directory structure under `translated/<lang>/`

### Pull Request Automation

After translation completes, the workflow automates delivery through the `peter-evans/create-pull-request@v5` action. For each target language, it creates a dedicated branch named `translation/<lang>`, commits the translated files, and opens a pull request targeting `main`.

The generated PR includes a summary of changed files, a link to the triggering workflow run for traceability, and a standardized title format: `🤖 Automated translation – <lang>`.

## Step-by-Step Translation Flow

The complete pipeline executes through seven distinct phases:

1. **Trigger Detection** – The workflow activates on every push to `main` or according to the defined cron schedule.

2. **Repository Checkout** – The `actions/checkout` action pulls the latest repository state into the GitHub Actions runner.

3. **Environment Configuration** – The workflow exports the Azure Translator API key and target language list as environment variables, ensuring secure credential handling through GitHub Secrets.

4. **Container Execution** – The Docker container launches with the following configuration:

```yaml
- name: Run translation container
  uses: docker://ml-for-beginners/translator:latest
  env:
    AZURE_TRANSLATOR_KEY: ${{ secrets.AZURE_TRANSLATOR_KEY }}
    LANGUAGES: ${{ env.LANGUAGES }}
  with:
    args: >
      python /app/scripts/translate.py
      --source-dir ${{ github.workspace }}
      --output-dir /tmp/translated

```

5. **Content Processing** – Within the container, the Python script iterates through files:

```python
for lang in args.languages.split(','):
    for file_path in find_markdown_files(args.source_dir):
        text = extract_text(file_path)
        translated = call_azure_translator(text, lang, api_key=args.key)
        write_translated_file(file_path, translated, args.output_dir, lang)

```

6. **Branch and PR Creation** – The workflow creates language-specific branches and opens pull requests for human review:

```yaml
- name: Create PR for ${{ matrix.lang }}
  uses: peter-evans/create-pull-request@v5
  with:
    token: ${{ secrets.GITHUB_TOKEN }}
    branch: translation/${{ matrix.lang }}
    title: "🤖 Automated translation – ${{ matrix.lang }}"
    body: |
      This PR contains the ${{ matrix.lang }} version of the tutorial material,
      generated by the Co‑op Translator workflow.
    commit-message: "Add ${{ matrix.lang }} translations"

```

7. **Community Review** – Maintainers and contributors review the automated translations, make necessary linguistic adjustments, and merge approved content into `main`.

## Design Benefits and Security Features

The Co-op Translator architecture prioritizes reliability, security, and community collaboration.

**Environment Isolation** – Running the translation engine inside a Docker container eliminates dependency conflicts and ensures reproducible execution across different GitHub Actions runners. The container encapsulates all Python requirements and API client logic.

**Credential Safety** – The `AZURE_TRANSLATOR_KEY` is stored as a repository secret and injected at runtime. GitHub Actions automatically masks this value in logs, preventing accidental exposure in workflow outputs.

**Scalable Language Support** – Adding new languages requires only updating the `LANGUAGES` environment variable. The same Docker image and Python script process additional targets without code modifications, enabling parallel translation jobs through matrix strategies.

**Human-in-the-Loop Verification** – By generating pull requests rather than committing directly to `main`, the system ensures that native speakers and subject matter experts review all automated translations before publication. This maintains educational quality while reducing manual translation workload.

## Summary

- The **Co-op Translator** uses [`.github/workflows/co-op-translator.yml`](https://github.com/microsoft/ML-For-Beginners/blob/main/.github/workflows/co-op-translator.yml) to orchestrate automated translation on every push to `main` and nightly schedules.
- A **Docker container** built from `docker/Dockerfile` executes [`scripts/translate.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/scripts/translate.py), which processes `.ipynb`, `.md`, and `.html` files through the Microsoft Translator Text API.
- The system extracts human-readable text while preserving code blocks and formatting, then reinserts translations into properly structured output files.
- **Security measures** include secret masking for the `AZURE_TRANSLATOR_KEY` and isolated container execution.
- Automated **pull request creation** via `peter-evans/create-pull-request@v5` ensures human review before translations merge into the repository.
- New languages can be added by updating the `LANGUAGES` environment variable without modifying the core translation logic.

## Frequently Asked Questions

### How does the Co-op Translator handle different file formats?

The [`scripts/translate.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/scripts/translate.py) engine specifically processes Jupyter notebooks (`.ipynb`), Markdown (`.md`), and HTML files. It extracts only human-readable content while ignoring code blocks, ensuring that programming examples remain unchanged while translating explanatory text. The script preserves the original file structure and cell metadata when generating translated versions.

### What security measures protect the Azure Translator API key?

The workflow stores the API key as a GitHub repository secret (`secrets.AZURE_TRANSLATOR_KEY`) and injects it into the Docker container as the `AZURE_TRANSLATOR_KEY` environment variable. GitHub Actions automatically masks secret values in job logs, preventing exposure in workflow outputs. The key is never written to disk within the repository itself.

### Can the system be extended to support additional languages?

Yes. The workflow supports scalability through the `LANGUAGES` environment variable. Adding a new language requires only appending its language code (e.g., `"ja"` for Japanese) to this comma-separated list. The same Docker image and Python processing logic handle the new target without requiring modifications to [`translate.py`](https://github.com/microsoft/ML-For-Beginners/blob/main/translate.py) or the Dockerfile.

### Why does the workflow create pull requests instead of pushing directly to main?

The pull request workflow implements a **human-in-the-loop** quality control process. While the Microsoft Translator Text API provides accurate machine translation, educational content requires domain-specific terminology verification and cultural adaptation. Pull requests allow maintainers and community contributors to review, edit, and approve translations before they become the definitive multilingual version of the curriculum.