Install Ponyglot with an AI agent
This page is written for coding agents such as Claude Code, Cursor or Copilot, and for the people who use them. It gives the exact steps to add Ponyglot to a Django project, and marks the steps that need a person. A plain-text index of everything is at /llms.txt.
Status: early access (alpha). Accounts are invite-only; the agent can do all the local setup without one.
Rules for agents
- Don’t publish content. Ponyglot delivers translations as drafts (django CMS, Wagtail) or
as suggestions (models). Leave publishing and applying to an editor. Don’t set
PUBLISH_BY_DEFAULTunless the person asks for it. - Don’t spend money without approval. Requesting translation is billed. Run
ponyglot translate --estimatefirst, show the result, and only runponyglot translateafter the person agrees. Never add--yes(confirms large jobs) on your own. - Keep the API key out of the repository. Read it from the environment
(
PONYGLOT_API_KEY); don’t write it into settings files or commit it. - Account, subscription and API key are the person’s job. Don’t try to sign up or buy a plan; tell the person what’s needed (step 5).
1. Detect the stack
Check the project’s dependencies and INSTALLED_APPS:
| Found | Content | Install | Add to INSTALLED_APPS |
|---|---|---|---|
cms (django CMS 5.1+) |
Pages, posts, aliases, other frontend-editable models | pip install "djangocms-ponyglot[versioning]" |
"ponyglot", "djangocms_ponyglot" |
wagtail and wagtail_localize |
Pages and snippets | see below | "ponyglot", "wagtail_ponyglot" |
parler |
Models translated with django-parler | pip install "ponyglot[parler]" |
"ponyglot", "ponyglot.contrib.parler" |
modeltranslation |
Models translated with django-modeltranslation (also wagtail-modeltranslation) | pip install "ponyglot[modeltranslation]" |
"ponyglot", "ponyglot.contrib.modeltranslation" |
locale/ directories with .po files |
Interface strings (gettext) | pip install "ponyglot[gettext]" |
none, see step 8 |
Combine them as needed ("ponyglot" only once). A django CMS site with djangocms-stories or another
parler app usually needs both djangocms_ponyglot and ponyglot.contrib.parler.
Wagtail: the wagtail-ponyglot connector isn’t publicly available yet; the package on PyPI is
only a name reservation. Don’t install it. Tell the person to ask at hello@ponyglot.app for early
access. Models translated with wagtail-modeltranslation work today through
ponyglot[modeltranslation].
Requirements: Python 3.10+, Django 5.2+. django CMS 5.1+; without djangocms-versioning 2.7+, translations can’t arrive as drafts and wait until an editor applies them. For django-modeltranslation, Ponyglot only fills languages whose database columns already exist.
If none of these libraries is installed, the project has no translatable content in the database yet. Choosing a translation library is a design decision for the person, not part of this setup.
2. Install and configure
Add the package to the project’s dependency file (pyproject.toml, requirements.txt, …) the way
the project already does it, then install. Add to the settings:
import os
INSTALLED_APPS += [
"ponyglot",
"djangocms_ponyglot", # django CMS
"ponyglot.contrib.parler", # django-parler models
]
PONYGLOT = {
"API_KEY": os.environ.get("PONYGLOT_API_KEY", ""),
"SOURCE_LANGUAGE": "en", # the language editors write in; must be in LANGUAGES
}
Use the project’s existing way of reading environment variables if it has one (django-environ,
python-decouple, …). The site’s languages come from LANGUAGES; set PONYGLOT["LANGUAGES"] only
to limit them. All settings: connector settings.
3. Migrate and check
python manage.py migrate
python manage.py check
Without an API key, check shows the warning ponyglot.W001. That’s expected at this point.
ponyglot.E001 means SOURCE_LANGUAGE isn’t one of the site’s languages: fix it before going on.
4. Count the content (no account needed)
python manage.py ponyglot backfill --dry-run
This runs locally and sends nothing. It prints the number of units, segments and source characters.
Show it to the person: it’s the size of the first translation. Characters are counted per target
language, so multiply by the number of target languages. Translation-memory hits and existing
translations aren’t billed. For django CMS, python manage.py ponyglot_fields --translated lists
which plugin fields will be translated.
5. What the person does
Stop here and tell the person:
- Account: request an invitation at hello@ponyglot.app (early access).
- Site: in the dashboard at app.ponyglot.app, create a site with the source and target languages.
- API key: on the site’s page, under API keys (needs the admin or owner role).
Store it as the environment variable
PONYGLOT_API_KEYlocally and in deployment. - Subscription: connecting and pushing content works without one; requesting hosted translation needs a subscription that covers the site. See plans.
6. Connect and push the content
With PONYGLOT_API_KEY set:
python manage.py ponyglot check # settings and connection; non-zero exit on failure
python manage.py ponyglot backfill # first push of all existing content
python manage.py ponyglot status # per language: ✓ / stale / review / missing
Existing translations are imported on the first push, so nothing is translated twice.
Then make the sync run regularly. Saving content only marks it as changed; ponyglot sync pushes
changes, reports editors’ reviews and fetches translations. Add it the way the project runs
background work, for example:
# worker process (Procfile, systemd, container)
python manage.py ponyglot sync --loop 60
# or cron, every few minutes
*/5 * * * * cd /path/to/project && python manage.py ponyglot sync
See run the sync.
7. Translate (needs the person’s approval)
python manage.py ponyglot translate --estimate # cost; nothing is sent to an engine
python manage.py ponyglot translate --wait # after the person agreed
python manage.py ponyglot translate --language fr --estimate # one language
python manage.py ponyglot sync # fetch the translations
If translate says the job needs confirmation, show the estimate to the person; add --yes only
if they confirm.
Where the translations arrive, for the person to review:
- django CMS: as drafts; toolbar › Language › Ponyglot translations.
- Models: admin › Ponyglot › Translation suggestions, with a diff; Apply or Reject.
Add
PonyglotAdminMixinto the model admins for per-object dialogs (how-to). - Whole site: admin › Ponyglot › Translation dashboard.
8. .po files (optional)
export PONYGLOT_API_KEY=pg_… # a site with the gettext adapter
python manage.py makemessages -l de -l fr
ponyglot po sync locale # writes translations into the .po and .mo files
Run it on a checkout of the default branch and commit the result to a review branch. Merging is the approval. Don’t merge it yourself.
When something fails
Commands exit non-zero with a message on failure.
| Message | Fix |
|---|---|
No adapter installed |
Add an adapter (step 1) to INSTALLED_APPS. |
ponyglot.W001 |
No API key yet (step 5). |
ponyglot.E001 |
Set PONYGLOT["SOURCE_LANGUAGE"] to one of LANGUAGES. |
subscription_inactive or HTTP 402 |
No active subscription for this site; the person handles billing. |
This job needs confirmation |
Show the estimate; --yes only with the person’s OK. |
More: install guide, connector commands, docs. Questions: hello@ponyglot.app.
Ponyglot is a personal project of Fabian Braun, the django CMS fellow; it is not a product of the django CMS Association. Connectors are BSD-3-Clause.