publishpress / translations
AI-powered translation automation for PublishPress plugins using Potomatic
Package info
github.com/publishpress/library-publishpress-translator
Language:JavaScript
pkg:composer/publishpress/translations
Requires
- php: >=7.2.5
- ext-json: *
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- automattic/vipwpcs: ^3.0
- overtrue/phplint: ^2.1
- phpcompatibility/php-compatibility: ^9.3
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.0
- publishpress/publishpress-phpcs-standards: dev-main
- sirbrillig/phpcs-variable-analysis: ^2.11
- squizlabs/php_codesniffer: ^3.8
- szepeviktor/phpstan-wordpress: ^1.3
- wp-coding-standards/wpcs: ^3
This package is auto-updated.
Last update: 2026-03-04 07:53:41 UTC
README
AI-powered translation automation for PublishPress plugins using Potomatic, OpenAI, and Weblate.
Features
- AI-powered translations using OpenAI GPT models
- Weblate integration for translation management and human review
- Automatic upload/download to/from Weblate
- Merges with existing translations (preserves manual edits)
- Cost-effective (~$0.03 per language for 1,744 strings)
- Supports 10+ languages by default
- Dry-run mode for cost estimation
- Automatic detection of
.potfiles
Requirements
- PHP 7.2.5 or higher
- PHP extensions:
json,zip(usually enabled by default) - Node.js 18+ and npm (for Potomatic CLI tool)
- OpenAI API key (Get one here)
- Weblate account and API token (Sign up here)
- Plugin must have a
languages/directory containing one or more.potfiles
Installation
Note: This setup works the same whether you're working from the plugin root or inside dev-workspace.
Recommended setup:
Step 1: Add to root composer.json
{
"require-dev": {
"publishpress/translations": "^1.0.0"
},
"scripts": {
"translate": "vendor/bin/publishpress-translate",
"translate:dry-run": "vendor/bin/publishpress-translate --dry-run",
"translate:download": "vendor/bin/publishpress-translate --download",
"translate:upload": "vendor/bin/publishpress-translate --upload",
"translate:custom": "vendor/bin/publishpress-translate --languages",
"translate:force": "vendor/bin/publishpress-translate --force",
"translate:force-custom": "vendor/bin/publishpress-translate --force --languages"
}
}
Step 2: Install
composer update
Usage
Set Environment Variables
Before using the translation tools, set your API keys as environment variables:
Create a .env file in your plugin root with your API keys:
OPENAI_API_KEY=sk-proj-your-openai-key
WEBLATE_API_TOKEN=wlu_your-weblate-token
The .env file is automatically loaded when you run the translation tool. No additional configuration needed.
Values can be quoted or unquoted:
OPENAI_API_KEY="sk-proj-your-openai-key"
WEBLATE_API_TOKEN='wlu_your-weblate-token'
Alternatively, you can set environment variables directly in your shell:
Windows (PowerShell):
$env:OPENAI_API_KEY="sk-proj-your-openai-key" $env:WEBLATE_API_TOKEN="wlu_your-weblate-token"
Windows (CMD):
set OPENAI_API_KEY=sk-proj-your-openai-key set WEBLATE_API_TOKEN=wlu_your-weblate-token
Mac/Linux:
export OPENAI_API_KEY=sk-proj-your-openai-key export WEBLATE_API_TOKEN=wlu_your-weblate-token
Or create a .env file in your plugin root (don't commit this!):
OPENAI_API_KEY=sk-proj-your-openai-key
WEBLATE_API_TOKEN=wlu_your-weblate-token
Note: Shell environment variables take precedence over
.envfile values.
Get your Weblate API token:
- Sign up at weblate.publishpress.com
- Go to your profile: https://weblate.publishpress.com/accounts/profile/#api
- Copy your personal API key
Additional configuration
The following environment variables control advanced behaviour:
-
OPENAI_API_KEY(required for live translation) Used to call the OpenAI API. If it is missing:- In dry run mode, the tool prints a warning but continues so you can verify the workflow without incurring cost.
- In live mode, the tool prints a clear warning and exits before making any API calls.
-
WEBLATE_API_TOKEN(optional for AI generation, required for Weblate sync) If not set, Weblate integration is disabled:- You can still generate local translations.
- Upload/download with Weblate will be skipped and a warning will be printed.
-
WEBLATE_API_URL(optional, default:https://hosted.weblate.org/api/) Set this to your Weblate base URL (ending in/api/) when using a self-hosted instance. -
WEBLATE_SKIP_VCS(optional, default:true) Skip all VCS (repository) operations when interacting with Weblate. By default, VCS is skipped to avoid requiring repository configuration. Set tofalseor0to enable VCS operations if your project has a configured repository URL in Weblate. -
WEBLATE_API_TIMEOUT(optional, default:120seconds) HTTP timeout used for Weblate API requests. For large projects or slow connections this may be too short. You can increase it, for example:export WEBLATE_API_TIMEOUT=300 -
WEBLATE_UPLOAD_DELAY(optional, default:2seconds) Delay between uploading translation files to Weblate. Useful to avoid rate limiting or server overload when uploading many languages.export WEBLATE_UPLOAD_DELAY=5 -
WEBLATE_PROJECT_SLUG(optional) Override the Weblate project slug. By default, uses the plugin slug fromcomposer.json. -
WEBLATE_COMPONENT_SLUG(optional) Override the Weblate component slug. By default, uses the text domain from the.potfile. -
WEBLATE_GIT_BRANCH(optional, default:development) Specify which Git branch Weblate should use for the component. -
WEBLATE_REPO_TYPE(optional, default:https) Repository access type:httpsorssh. Usesshif you have SSH keys configured in Weblate. -
WEBLATE_REPO_URL(optional) Override the repository URL for Weblate. Useful for private repositories or custom Git hosting. Examples:- HTTPS with credentials:
https://username:token@github.com/owner/repo.git - SSH:
git@github.com:owner/repo.git
- HTTPS with credentials:
-
WEBLATE_PUSH_URL(optional) Override the push URL separately from the repository URL. Only needed if push and pull URLs differ. -
WEBLATE_PREFER_BASE_LANGUAGE(optional, default:false) When downloading from Weblate, prefer base language codes (e.g.,deoverde_DE) when duplicate locale variants exist. Set totrueor1to enable.export WEBLATE_PREFER_BASE_LANGUAGE=true -
WEBLATE_CLEAN_EXISTING_TRANSLATIONS(optional, default:false) Delete all existing.pofiles before downloading from Weblate. Useful for a clean slate when syncing translations. Set totrueor1to enable.export WEBLATE_CLEAN_EXISTING_TRANSLATIONS=true -
SKIP_LANGUAGES(optional, default:it_IT,es_ES,fr_FR,pt_BR) Comma-separated list of language codes to skip during translation, upload, and download. These languages are typically handled by human translators. The default skipped languages are merged with any custom ones you specify.export SKIP_LANGUAGES=it_IT,es_ES,fr_FR,pt_BR
Complete Translation Workflow
1. Run Translation (Full Cycle)
From dev-workspace:
# Enter dev-workspace ./run # Dry run (preview cost, no API calls) composer translate:dry-run # Full translation cycle composer translate
From plugin root:
# Dry run composer translate:dry-run # Full translation cycle composer translate
What happens when you run composer translate:
- 📥 Download - Pulls existing translations from Weblate (if project exists)
- 🤖 AI Translate - Potomatic adds translations for new/missing strings
- 📤 Upload - Pushes updated translations back to Weblate
This ensures:
- Existing translations are preserved
- Only new/missing strings are translated by AI
- Weblate always has the latest translations
2. Review & Improve in Weblate
After running translate, you can visit your project in Weblate:
- Hosted Weblate: https://hosted.weblate.org/projects/YOUR-PROJECT/
- Self-hosted Weblate: https://YOUR-WEBLATE-DOMAIN/projects/YOUR-PROJECT/
- Review and improve AI-generated translations
- Use Weblate's translation memory and suggestions
- Collaborate with community translators
3. Download Only
If you just want to download the latest translations without running AI translation:
# Download latest from Weblate (no AI translation)
composer translate:download
Use this when:
- Translators made changes in Weblate
- You want to sync before building plugin
- You don't need to add new translations
Advanced options:
# Translate custom languages only vendor/bin/publishpress-translate --languages=de_DE,fr_FR,es_ES # Force re-translate all strings (ignore existing translations) vendor/bin/publishpress-translate --force # Download specific languages only vendor/bin/publishpress-translate --download --languages=de_DE,fr_FR # Upload specific languages only (no AI translation) vendor/bin/publishpress-translate --upload --languages=de_DE,fr_FR
Note: The library automatically detects your environment (dev-workspace vs plugin root) and uses the correct vendor path.
Default Languages
The tool translates into these languages by default:
- German (de_DE)
- Indonesian (id_ID)
- Filipino (fil)
- Russian (ru_RU)
- Yoruba (yo)
- Finnish (fi)
- Japanese (ja)
- Korean (ko_KR)
Skipped Languages
The following languages should not be translated by Potomatic, they are handled by human translators:
- Italian (it_IT)
- Spanish (es_ES)
- French (fr_FR)
- Brazilian Portuguese (pt_BR)
These languages will be skipped during translation and upload processes, even if PO files exist for them.
Preventing Plugin Name Translation
By default, all strings in your plugin are translated, including the plugin name. To keep your plugin name untranslated, add it to your composer.json file:
{
"extra": {
"plugin_name": "your plugin name"
}
}
The translation tool will then automatically keep the plugin name untranslated in all PO files, both when:
- Running AI translations with Potomatic
- Downloading translations from Weblate
How It Works
Translation Cycle (composer translate)
Step 1: Download from Weblate
- Pulls existing translations from Weblate
- Preserves human edits and community contributions
- Creates project if it doesn't exist yet
Step 2: AI Translation with Potomatic
- Scans your plugin's
languages/directory for.potfiles - Generates AI translations for new/missing strings only
- Merges with existing translations (preserves manual edits)
- Creates/updates
.poand.mofiles for each target language
Step 3: Upload to Weblate
- Creates project on Weblate (using plugin slug as project slug)
- Creates component for each text domain
- Uploads POT template and all PO translations
- Provides link to view/edit in Weblate
Download Only (composer translate:download)
- Connects to Weblate using your API token
- Finds your plugin's project and components
- Downloads latest
.pofiles for all languages - Converts to
.mofiles for WordPress - Saves to your
languages/folder
Use this when:
- You want to sync translations before building
- Translators made changes in Weblate
- You don't need to run AI translation
Weblate Integration
- Automatic sync - Download → Translate → Upload in one command
- Preserves human edits - Existing translations are never overwritten
- Automatic project creation - Uses plugin slug as project name
- Component per text domain - Each
.potfile becomes a component - Optional - Works without Weblate if token not set
One-Time Setup
Set your API keys permanently:
Windows:
[System.Environment]::SetEnvironmentVariable('OPENAI_API_KEY', 'sk-proj-your-key', 'User') [System.Environment]::SetEnvironmentVariable('WEBLATE_API_TOKEN', 'wlu_your-token', 'User')
Mac/Linux (add to ~/.bashrc or ~/.zshrc):
export OPENAI_API_KEY=sk-proj-your-key export WEBLATE_API_TOKEN=wlu_your-token
Troubleshooting
"Potomatic not found" Error
This shouldn't happen if you installed via Composer. If it does, please report it as a bug.
"OPENAI_API_KEY not set" warning / exit
If OPENAI_API_KEY is not configured:
- In dry run (
composer translate:dry-run), the tool prints a warning but continues so you can verify configuration without any API calls. - In live mode (
composer translate), the tool prints a clear message and exits before attempting any OpenAI requests.
Make sure you've set the environment variable before running live translations.
"Weblate not configured" Error
This appears when running --download without WEBLATE_API_TOKEN set. Weblate integration is optional for generation but required for download.
"No .pot files found" Error
Ensure your plugin has a languages/ directory with .pot translation template files. Generate these using tools like:
Weblate Upload Fails
If Weblate upload fails, the translation process continues (translations are still saved locally). Check:
- API token is correct
- You have permissions on Weblate
- Project/component names are valid (no special characters)
Development
Clone the Repository
git clone https://github.com/publishpress/translations.git
cd translations
composer install
Testing Locally
To test the library before publishing:
- In your plugin's
composer.json, add a repository:
{
"repositories": [
{
"type": "path",
"url": "../publishpress-translations"
}
],
"require": {
"publishpress/translations": "@dev"
}
}
- Run
composer install
License
GPL-3.0-or-later
Credits
Built with Potomatic by GravityKit.