GitHub Actions
Copy these pipeline files and customize as needed.
AI Translation Workflow
Section titled “AI Translation Workflow”This workflow automatically extracts untranslated strings and translates them using Claude AI, then applies the translations back to your repository.
Workflow:
- Triggered when English locale files change on main branch
- Extracts new/changed strings using LocaleOps
- Sends strings to Claude API for translation
- Applies translated strings and creates a PR
Requirements:
- GITHUB_TOKEN: Automatically provided by GitHub Actions
- ANTHROPIC_API_KEY: Must be set in repository secrets
Setup Instructions:
1. Allow GitHub Actions to create and approve pull requests- Go to Settings → Actions → General in your repository.- Under "Workflow permissions", enable "Allow GitHub Actions to approve pull requests"
2. Enable AI TranslationsAdd your Anthropic API key as a GitHub secret:- Go to Settings → Secrets and variables → Actions- Add `ANTHROPIC_API_KEY`name: AI translation
on: push: branches: [main] paths: - "src/i18n/locales/en/**" # Only trigger when English (source) locale changes
# Prevent multiple translation workflows from running simultaneouslyconcurrency: group: localeops_ai cancel-in-progress: false
jobs: translate: runs-on: ubuntu-latest permissions: contents: write # Required to push commits pull-requests: write # Required to create pull requests
steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }}
# Configure git for commits created by LocaleOps - run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com"
- name: extract and translate env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub token for LocaleOps ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} # Claude API key run: | set -e
# Step 1: Extract untranslated strings using LocaleOps out=$(npx @localeops/localeops extract)
# Step 2: Transform extracted data into flat array for translation # Collect all items needing translation (added or changed strings) # Output format: [{locale, filePath, resourcePath, text}, ...] to_translate=$(echo "$out" | jq '[to_entries[] | .key as $loc | .value[] | select(.type == "added" or .type == "changed") | {locale: $loc, filePath, resourcePath, text: (if .type == "added" then .value else .newValue end)}]')
# Exit early if nothing needs translation [ "$(echo "$to_translate" | jq 'length')" -eq 0 ] && echo "Nothing to translate" && exit 0
# Step 3: Send strings to Claude API for translation response=$(curl -s https://api.anthropic.com/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d "$(jq -n --arg items "$to_translate" '{ model: "claude-sonnet-4-20250514", max_tokens: 8192, messages: [{role: "user", content: "Translate each item to its target locale. Keep placeholders like {name}, {{count}}, %s intact.\n\nReturn JSON array: [{\"locale\": \"...\", \"filePath\": \"...\", \"resourcePath\": \"...\", \"value\": \"<translation>\", \"from\": \"<original>\"}]\n\nItems:\n\($items)"}] }')")
echo "[DEBUG] API Response: $response"
# Step 4: Extract translated text from Claude's response # Remove markdown code blocks if present translated=$(echo "$response" | jq -r '.content[0].text' | sed 's/```json//g; s/```//g')
echo "[DEBUG] Extracted translations: $translated"
# Step 5: Reorganize translations by locale for LocaleOps apply command # Transform from array to object: {locale: [{filePath, resourcePath, value, from}]} translations_by_locale=$(echo "$translated" | jq 'group_by(.locale) | map({ (.[0].locale): map({filePath, resourcePath, value, from}) }) | add')
echo "[DEBUG] Grouped by locale: $translations_by_locale"
# Step 6: Apply translations and create PR npx @localeops/localeops apply "$translations_by_locale"Apply Translations Workflow
Section titled “Apply Translations Workflow”This workflow applies completed translations to your repository. It’s designed for asynchronous translation workflows where translations are completed by external services, human translators, or APIs.
Workflow:
- Triggered via repository_dispatch event
- Receives translations in the event payload
- Applies translations using LocaleOps
- Creates a pull request with the changes
Trigger this workflow using GitHub API:
curl -X POST \ -H "Authorization: token YOUR_GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ https://api.github.com/repos/OWNER/REPO/dispatches \ -d '{"event_type":"localeops_apply","client_payload":{"translations":{...}}}'Requirements:
- GITHUB_TOKEN: Automatically provided by GitHub Actions
name: apply translations
on: repository_dispatch: types: [localeops_apply] # Triggered via repository_dispatch event
# Prevent multiple apply workflows from running simultaneouslyconcurrency: group: localeops_apply cancel-in-progress: false
jobs: apply_translations: runs-on: ubuntu-latest permissions: contents: write # Required to push commits pull-requests: write # Required to create pull requests
steps: - name: checkout uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }}
# Configure git for commits created by LocaleOps - name: configure git run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com"
# Extract translations from repository_dispatch payload # The payload should contain: {translations: {locale: [{filePath, resourcePath, value}]}} - name: set env vars run: | { echo "TRANSLATIONS<<EOF" echo '${{ toJson(github.event.client_payload.translations) }}' echo "EOF" } >> "$GITHUB_ENV"
# Apply translations to locale files and create PR - name: run localeops env: TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub token for creating PR run: npx @localeops/localeops apply "${TRANSLATIONS}"Extract Strings Workflow
Section titled “Extract Strings Workflow”This workflow extracts untranslated and changed strings from your locale files. It’s designed for manual or external translation workflows where you want to extract strings without automatically translating them.
Workflow:
- Triggered via repository_dispatch event
- Extracts new/changed strings using LocaleOps
- Outputs the extraction result (can be sent to external service)
The output is a JSON object containing:
- New strings (type: “added”)
- Changed strings (type: “changed”)
- Organized by locale, file path, and resource path
Example output:
{ "es": [ {"type": "added", "filePath": "common.json", "resourcePath": "hello", "value": "Hello"} ]}Trigger this workflow using GitHub API:
curl -X POST \ -H "Authorization: token YOUR_GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ https://api.github.com/repos/OWNER/REPO/dispatches \ -d '{"event_type":"localeops_extract"}'Use cases:
- Send extracted strings to a translation agency
- Export to CSV/Excel for human translators
- Trigger external translation API
- Review what needs translation before processing
Requirements:
- GITHUB_TOKEN: Automatically provided by GitHub Actions
name: extract strings
on: repository_dispatch: types: [localeops_extract] # Triggered via repository_dispatch event
# Prevent multiple extract workflows from running simultaneouslyconcurrency: group: localeops_extract cancel-in-progress: false
jobs: extract: runs-on: ubuntu-latest
steps: - name: checkout uses: actions/checkout@v4
# Extract untranslated strings and output the result # Note: You can pipe this output to external services or save it as an artifact - name: extract env: TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub token for accessing repository # DEBUG: "true" # (optional) Uncomment to enable debug output run: | output=$(npx @localeops/localeops extract) echo "$output"
# Optional: Save output as artifact for later use # echo "$output" > extraction-result.json
# Optional: Send to external service # curl -X POST https://your-translation-service.com/api/translate \ # -H "Content-Type: application/json" \ # -d "$output"