Skip to main content
Themes have their own translation domain, separate from the application’s. Getting the domain right is the difference between a translated theme and one that silently falls back to English.

Use the theme domain

A plain __() in a theme template looks up the application’s catalog. Your translation won’t be found, and the extractor won’t add the string to your catalogs.

Catalog layout

  • One directory per language, named with the xx-XX code.
  • The file is always theme.po.
  • The header sets X-Domain: theme.
static/locale/de-DE/LC_MESSAGES/theme.po
The application loads the active theme’s catalog for the resolved language on every request.

Extract strings

Run the console commands from the Aikeedo installation, pointing at your theme’s repository:
The command finds your package inside the repository, scans the templates, and writes catalogs next to the manifest, using the theme domain.
The starter kit used to ship its own extraction script. It was removed: use these console commands, which share the application’s parser and won’t mangle quoting.

Translate

This fills in missing entries with an AI model. Add --force to redo existing translations, and --dry-run to preview. Review the output before release: marketing copy is where machine translation is weakest.

Working on the installed copy

Point --path at your repository, not at extra/extensions/.... The installed copy is overwritten by the next build, so edits there are lost.

When a language shows English

The theme’s language is resolved from the URL prefix, then the user’s preference, then the locale cookie, then the browser’s Accept-Language, then the default. Three things must line up:
The language is enabled in Settings → Languages.
Your theme has a theme.po for it.
The string uses the theme domain.
If the theme has no catalog for the resolved language, the locale global is null, which is why every template should use locale.code|default('en-US').

Translating JavaScript strings

Strings that only exist in the browser go through the theme’s own small helper, which reads a catalog exposed as window.locale. Prefer translating in Twig and passing the result into your component, and keep the JavaScript path for strings built at runtime.

RTL languages

Each locale carries a dir. Set it on the document and use logical CSS properties so layouts mirror correctly:

Checklist

Every visible string uses a d-prefixed helper with the theme domain.
Contexts are used for short strings such as buttons and headings.
Catalogs exist for the languages you support, with X-Domain: theme.
Extraction was re-run after the last copy change.
static/locale/ is included in your release archive.
The layout handles dir and a null locale.