AI translation workflow
Automating po and json translation through Azure AI Translator and a central workflow
This document explains how to integrate automated translation of localization
files (.po and .json) using Azure AI Translator and a centralized
GitHub Actions workflow. The system supports context-aware translations
and generates automated PRs with translated content.
Powered by
- Azure Cognitive Services, Translator
- GitHub Actions for automation
.poand.jsonlocalization files- Support for gettext-style context handling (
msgctxt,_x())
How it works
Centralized workflow
The parent workflow
(newfold-labs/workflows/.github/workflows/auto-translate.yml) automates:
- Scanning
.poand.jsonfiles - Translating strings only if untranslated
- Respecting context from
_x()or JSON keys likemsgid|context - Submitting a PR with the translated content
Child repositories only need a minimal dispatcher workflow.
Setup for plugin and module repositories (child)
1. Create the workflow in your plugin repo
In .github/workflows/auto-translate.yml:
name: Auto Translate
on:
push:
branches: [main]
workflow_dispatch:
inputs:
text_domain:
description: "Text domain (optional)"
required: false
default: ""
permissions:
contents: write
pull-requests: write
jobs:
translate:
uses: newfold-labs/workflows/.github/workflows/auto-translate.yml@main
with:
text_domain: ${{ github.event.inputs.text_domain || 'your-plugin-textdomain' }}
secrets:
TRANSLATOR_API_KEY: ${{ secrets.TRANSLATOR_API_KEY }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
2. Localization file naming convention
Ensure your translation files follow this pattern:
.pofiles:my-plugin-textdomain-fr_FR-*.po,my-plugin-textdomain-es_ES-*.po, etc..jsonfiles (e.g. for WordPress block editors):my-plugin-textdomain-fr_FR-*.json, etc.
The text domain must be included in the filename.
3. Use _x() or context-aware keys
To support contextual translations, use:
-
PHP:
_x( 'Book', 'noun', 'my-plugin-textdomain' ); _x( 'Book', 'verb', 'my-plugin-textdomain' ); -
JSON message keys (gettext style):
{ "locale_data": { "messages": { "Save\u0004button": [""], "Save\u0004menu": [""] } } }
4. Translation skips
The workflow skips:
- Any
.poor.jsonentry that already has a translation - Empty keys or metadata entries
- Malformed or non-standard entries
Secrets required
Stored only in the central repo:
| Secret name | Purpose |
|---|---|
TRANSLATOR_API_KEY |
Azure Translator API key |
PERSONAL_ACCESS_TOKEN |
GitHub token with PR permissions |
No need to store these secrets in child or plugin repos.
Pull request details
- Title:
Auto-translated files update -
Body:
This PR contains automatic translations of PO and JSON files using Azure AI Translator. Context-aware translations are handled for `_x()` and similar methods.
Tips for plugin developers
- Always extract strings using WordPress i18n functions:
__(),_e(),_x(), etc. - Use context where possible (
_x()), especially for ambiguous terms. - Organize translation files per locale and per text domain.
- Avoid duplicating strings with different whitespace or punctuation, they’ll be treated separately.
Workflow triggers
- On every push to
main(auto PR generated) - On manual dispatch from the GitHub UI
Common pitfalls
| Mistake | Fix |
|---|---|
| File doesn’t include text domain | Rename file to follow pattern |
_x() not used for context |
Use _x() instead of __() where needed |
No .po or .json files |
Generate them using i18n tools like wp i18n make-pot |
Related
-
Internationalization
Making every user-facing string translatable, and the files that carry the translations
-
Crowdin translation workflow
Uploading source strings to Crowdin and getting translations back as a pull request