https://github.com/doloc-io/doloc-action
GitHub Action for automatic i18n translation with doloc. Supports XLIFF, JSON, Android XML, Angular, React Intl / FormatJS, and CI checks.
https://github.com/doloc-io/doloc-action
android angular doloc formatjs github-action github-actions i18n json l10n localization react-intl translation xliff
Last synced: about 2 hours ago
JSON representation
GitHub Action for automatic i18n translation with doloc. Supports XLIFF, JSON, Android XML, Angular, React Intl / FormatJS, and CI checks.
- Host: GitHub
- URL: https://github.com/doloc-io/doloc-action
- Owner: doloc-io
- License: mit
- Created: 2026-06-07T18:09:23.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-06-10T20:43:22.000Z (29 days ago)
- Last Synced: 2026-06-10T22:15:05.548Z (29 days ago)
- Topics: android, angular, doloc, formatjs, github-action, github-actions, i18n, json, l10n, localization, react-intl, translation, xliff
- Language: TypeScript
- Homepage: https://doloc.io/getting-started/frameworks/github-actions/
- Size: 267 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# doloc i18n Translation Action
Translate your i18n files directly in GitHub Actions — no translation platform required.
This action updates or checks localization files with the [doloc](https://doloc.io?utm_source=github&utm_medium=gh-action&utm_campaign=readme) API. It supports the same developer-first workflow as the CLI/curl examples: keep source files in your repository, run doloc when strings change, and decide yourself whether to commit, inspect, artifact, or open a pull request with the resulting diff.
## Quick start
1. Create a doloc API token at [doloc.io/account](https://doloc.io/account?utm_source=github&utm_medium=gh-action&utm_campaign=readme).
2. Add it to your repository secrets as `DOLOC_API_TOKEN`.
3. Pick the workflow that matches your team:
| 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 catches 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 same-repository feature branches, this is often the leanest workflow: a developer changes source text, CI commits updated translation files back to the same branch, and the existing PR shows the complete diff.
```yaml
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.json
```
The `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.
## Check mode
Use `mode: check` when translations should be updated locally but verified in CI. Check mode translates into memory, compares with committed target files, and fails if any target would change.
```yaml
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.json
```
## 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:
```yaml
on:
push:
branches:
- main
paths:
- src/lang/en.json
- .github/workflows/update-translations.yml
```
Use the same doloc and `git-auto-commit-action` steps from [Commit to feature branches](#commit-to-feature-branches). This keeps feature PRs simpler, but translation updates appear in a follow-up commit on `main`.
## XLIFF example
```yaml
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
targets: |
src/locale/messages.de.xlf
src/locale/messages.fr.xlf
```
For single-file formats such as XLIFF, the target file itself contains the translatable units, so `source` is not needed. Make sure the target language is configured inside the XLIFF file.
## React Intl / FormatJS JSON example
```yaml
- 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
```
## Android XML example
```yaml
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
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:fr
```
## Flutter ARB example
```yaml
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
source: lib/l10n/app_en.arb
targets: |
lib/l10n/app_de.arb
lib/l10n/app_fr.arb
```
## Target mappings
Use one mapping per line:
```yaml
targets: |
src/lang/de.json:de
src/lang/fr.json:fr
```
If each target has a different source file, use `=>`:
```yaml
targets: |
src/lang/en.json => src/lang/de.json:de
src/lang/en-GB.json => src/lang/fr.json:fr
```
The target language suffix (`:de`) is optional when the language can be inferred from the file name or is included in the file contents (e.g. XLIFF) or when you provide `target-lang` in single-target mode.
## doloc API options
Use the `options` input to pass doloc API query parameters. Add one option per line:
```yaml
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
source: src/lang/en.json
targets: |
src/lang/de.json:de
src/lang/fr.json:fr
options: |
untranslated=no-state,needs-translation
```
You can also pass complex DNF option values exactly as you would in a curl query string. For example, this XLIFF 1.2 setting translates units that either have no state and still equal the source text, or have the `needs-translation` state:
```yaml
- uses: doloc-io/doloc-action@v1
with:
token: ${{ secrets.DOLOC_API_TOKEN }}
targets: |
src/locale/messages.de.xlf
options: |
untranslated=no-state_target-equals-source,needs-translation
newState=translated
```
See the [doloc options reference](https://doloc.io/getting-started/options/?utm_source=github&utm_medium=gh-action&utm_campaign=readme) for supported query parameters and format-specific option links.
## Open a translation PR
You can compose this action with a pull request action to open a PR with the translation updates. This is useful when direct bot commits are blocked by branch protection rules or when you want to review generated translations separately from source text changes.
```yaml
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.json
```
The fixed `branch` value updates one reusable translation PR on later workflow runs. If you intentionally want a separate PR per run, add `branch-suffix: timestamp`, but prefer the fixed branch for routine translation updates.
## Try it manually
Manual runs are useful for a first smoke test or an occasional release refresh. Add this trigger to any update workflow:
```yaml
on:
workflow_dispatch:
```
For normal automation, prefer `push` or `pull_request` triggers with path filters.
## Inputs
| Input | Required | Default | Description |
| --- | --- | --- | --- |
| `token` | Yes | | doloc API token. Store it as a secret such as `DOLOC_API_TOKEN`. |
| `source` | No | | Default source localization file. Required for JSON, ARB and Android XML target files. Unused for XLIFF. |
| `target` | No | | Single target localization file. |
| `targets` | No | | Multiline target mapping. |
| `source-lang` | No | | Source language, passed as `sourceLang` to the API. |
| `target-lang` | No | | Target language for single-target mode. |
| `mode` | No | `update` | `update` or `check`. |
| `options` | No | | Additional doloc API query parameters, one per line. See [doloc options](https://doloc.io/getting-started/options/?utm_source=github&utm_medium=gh-action&utm_campaign=readme). |
| `fail-on-change` | No | `true` in check mode, `false` in update mode | Fail if changes are produced or would be produced. |
At least one of `target` or `targets` is required.
## Outputs
| Output | Description |
| --- | --- |
| `changed` | `true` if any target file changed or would change. |
| `changed-files` | Newline-separated list of changed files. |
| `processed-files` | Number of processed target files. |
The action also writes a GitHub Actions job summary with processed files and change status.
## Security notes
- Store the API token in GitHub Actions secrets.
- Use `permissions: contents: read` for update/check runs that only leave local working-tree changes.
- Add `contents: write` and `pull-requests: write` only when composing with commit or PR actions.
## Versioning
Use the moving major tag for normal workflows:
```yaml
uses: doloc-io/doloc-action@v1
```
This 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.
## Troubleshooting
### No doloc API token was provided
Add `token: ${{ secrets.DOLOC_API_TOKEN }}` and make sure the secret exists in the repository or organization.
### Target file not found
Create the target file before running the action. For JSON,
```json
{
}
```
is usually enough for a new target file. For Android XML or XLIFF, create a valid empty or initial localization file.
### Check mode failed
Run the same mapping in update mode, commit the changed files, and re-run CI.
### API authentication failed
Create a new token at [doloc.io/account](https://doloc.io/account?utm_source=github&utm_medium=gh-action&utm_campaign=readme) and update the `DOLOC_API_TOKEN` secret.