GitHub Actions
Use the official doloc GitHub Action to keep translation files current in CI.
This action can automatically translate files, check for stale translations, and can easily be integrated to commit or propose changes. It supports all formats that doloc supports, including React Intl / FormatJS JSON, Android XML resources, ARB (Flutter), and XLIFF 1.2/2.0.
Alternatively, you can run doloc locally, possibly integrated into your text extraction or build scripts. For a detailed discussion see When to run doloc.
Setup
Create an API token on your doloc account page, then add it to your GitHub repository secrets as DOLOC_API_TOKEN.
Pick the workflow that matches how your team treats generated translation files:
| Workflow | Best fit |
|---|---|
| Commit to feature branches | Same-repository branches where translation diffs should appear in the original PR. |
| Check translations in PRs | Local-first workflows where CI should catch stale translation files. |
| Commit after merge | Repositories that update generated translations only on the default branch. |
| Open a translation PR | Protected branches or teams that want generated translations reviewed separately. |
Commit to feature branches
For small teams and same-repository feature branches, this is often the cleanest workflow: a developer changes source text, CI commits updated translation files back to the same branch, and the existing PR shows the complete diff.
name: Update translations
on:
push:
branches-ignore:
- main
paths:
- src/lang/en.json
- .github/workflows/update-translations.yml
permissions:
contents: write
jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- id: doloc
uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
source: src/lang/en.json
targets: |
src/lang/de.json
src/lang/fr.json
- name: Commit translation updates
if: steps.doloc.outputs.changed == 'true'
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: Update translations
file_pattern: src/lang/de.json src/lang/fr.jsonThe paths filter intentionally watches the source file, not the generated target files. This runs the translation only when source text changed. Note, that in any case there there will only a commit when translations actually changed, so no redundant commits are created.
Use this only for trusted same-repository branches. For fork PRs, secrets are not available by default and you usually should not send untrusted contributor text to external APIs automatically.
Check translations in PRs
Use check mode when developers update translations locally and CI should only verify freshness:
name: Check translations
on:
pull_request:
permissions:
contents: read
jobs:
check-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
mode: check
source: src/lang/en.json
targets: |
src/lang/de.json
src/lang/fr.jsonCheck mode translates in memory, compares the result with committed files, and fails when updates are needed. It does not modify the working tree.
Commit after merge
If you do not want CI to mutate feature branches, update translations on the default branch after source text changes are merged:
on:
push:
branches:
- main
paths:
- src/lang/en.json
- .github/workflows/update-translations.ymlUse the same doloc and git-auto-commit-action steps from Commit to feature branches. This keeps feature PRs simpler, but translation updates appear in a follow-up commit on main.
Open a translation PR
If direct bot commits are blocked by branch protection or review policy, create a reusable translation PR instead:
name: Update translations
on:
push:
branches:
- main
paths:
- src/lang/en.json
- .github/workflows/update-translations.yml
permissions:
contents: write
pull-requests: write
jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- id: doloc
uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
source: src/lang/en.json
targets: |
src/lang/de.json
src/lang/fr.json
- name: Create pull request
if: steps.doloc.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v8
with:
commit-message: "Update translations"
title: "Update translations"
body: "Updated localization files using doloc."
branch: doloc/update-translations
delete-branch: true
add-paths: |
src/lang/de.json
src/lang/fr.jsonThe fixed branch value is intentional: peter-evans/create-pull-request updates the same open translation PR on later runs. If you explicitly want a separate PR per workflow run, add branch-suffix: timestamp, but use that sparingly.
File mappings
For most cases, the source and target language can be inferred from file contents or file name.
If this is not possible, you can explicitly specify the source language with source-lang and target languages with :lang suffixes in the targets list. See Android XML example below.
For React Intl / FormatJS JSON or generic JSON, pass one source file plus one or more targets:
source: src/lang/en.json
targets: |
src/lang/de.json
src/lang/fr.jsonFor Android XML resources, include source and target languages when the files do not carry enough language information:
source: app/src/main/res/values/strings.xml
source-lang: en
targets: |
app/src/main/res/values-de/strings.xml:de
app/src/main/res/values-fr/strings.xml:frFor XLIFF, the target file itself contains the translatable units, so source should not be used:
targets: |
src/locale/messages.de.xlf
src/locale/messages.fr.xlfMake sure the target language is configured inside each XLIFF file.
Options
The options input maps to doloc API query parameters, one option per line:
options: |
untranslated=no-state_target-equals-source,needs-translation
newState=translatedSee the Options reference for the general syntax and links to each format’s supported options.
Permissions and secrets
Use the smallest permission set that matches your workflow:
| Workflow | Permissions |
|---|---|
| Translate only or check mode | contents: read |
| Commit changed files | contents: write |
| Create pull requests | contents: write, pull-requests: write |
The doloc action itself only needs access to the checked-out files. Write permissions are needed only by later composed steps that commit files or create pull requests.
Versioning
Use the moving major tag for normal workflows:
uses: doloc-io/doloc-action@v1This action follows semantic versioning, so v1 will always point to the latest v1 release and does not introduce breaking changes. Pinning to a specific patch version is also possible, but usually not needed.
More details
See the doloc-action README for all inputs, outputs, target mapping syntax, and troubleshooting notes.