WP-CLI Commands

PerfLocale provides WP-CLI commands for managing languages, translations, strings, caches, and database integrity from the command line.

Namespace: wp perflocale

Languages

List Languages

wp perflocale languages list

Displays all configured languages in a table.

Options:

  • --format=<format> - Output format: table (default), json, csv, yaml.

Example:

$ wp perflocale languages list
+----+------+--------+-----------+---------+--------+-----------+
| ID | Slug | Locale | Name | Default | Active | Direction |
+----+------+--------+-----------+---------+--------+-----------+
| 1 | en | en_US | English | No | Yes | ltr |
| 2 | fr | fr_FR | French | Yes | Yes | ltr |
| 3 | de | de_DE | German | No | Yes | ltr |
| 4 | ar | ar | Arabic | No | Yes | rtl |
+----+------+--------+-----------+---------+--------+-----------+

$ wp perflocale languages list --format=json
[{"ID":"1","Slug":"en","Locale":"en_US",...}]

Add Language

wp perflocale languages add <locale> [--default]

Adds a new language.

Arguments:

  • <locale> (required) - WordPress locale code (e.g. fr_FR, es_ES, ar).

Options:

  • --default - Set as the default language.

RTL languages (Arabic, Hebrew, Farsi, Urdu, etc.) are auto-detected.

Examples:

# Add French
$ wp perflocale languages add fr_FR
Success: Language fr_FR added with ID 7 (direction: ltr).

# Add Arabic (RTL auto-detected)
$ wp perflocale languages add ar
Success: Language ar added with ID 8 (direction: rtl).

# Add as default language
$ wp perflocale languages add en_US --default

Delete Language

wp perflocale languages delete <slug>

Deletes a language. Prompts for confirmation. Cannot delete the default language.

Arguments:

  • <slug> (required) - Language slug (e.g. fr, de).

Example:

$ wp perflocale languages delete fr
Warning: 42 translation links use this language. They will be orphaned.
Are you sure you want to proceed? [y/n] y
Success: Language 'fr' deleted.

Safety features:

  • Warns if translations exist for this language.
  • Requires explicit confirmation (use --yes to skip in scripts).
  • Blocks deletion of the default language.

Translate

Single Post

wp perflocale translate <post_id> --to=<lang> [--provider=<provider>]

Translates a single post using machine translation.

Arguments:

  • <post_id> (required) - The post ID to translate.

Options:

  • --to=<lang> (required) - Target language slug.
  • --provider=<provider> - Provider: deepl, google, microsoft, libretranslate. Uses configured default if omitted.

Example:

$ wp perflocale translate 42 --to=de
Translating post 42 to de...
Success: Translated! New post ID: 99

Bulk Translation

wp perflocale translate --all --to=<lang> [--post-type=<type>] [--skip-existing]
wp perflocale translate --post-ids=<ids> --to=<lang> [--skip-existing]

Translates multiple posts with a progress bar.

Options:

  • --all - Translate all published posts of the given type.
  • --post-type=<type> - Post type for --all. Default: post.
  • --post-ids=<ids> - Comma-separated list of post IDs.
  • --to=<lang> (required) - Target language slug.
  • --skip-existing - Skip posts that already have a translation in the target language.
  • --provider=<provider> - Translation provider.

Examples:

# Translate all posts to German, skipping already translated
$ wp perflocale translate --all --to=de --post-type=post --skip-existing
Translating to de 100% [============================] 50 / 50
Success: Done. Translated: 38, Skipped: 12, Failed: 0.

# Translate specific posts to French
$ wp perflocale translate --post-ids=42,43,44 --to=fr
Translating to fr 100% [============================] 3 / 3
Success: Done. Translated: 3, Skipped: 0, Failed: 0.

# Translate all WooCommerce products
$ wp perflocale translate --all --to=fr --post-type=product --skip-existing

Notes:

  • Machine translation must be enabled in Settings → Machine Translation.
  • Failed translations are reported individually but don't stop the batch.
  • Progress bar shows real-time progress.

Translations

List Translations

wp perflocale translations list <post_id> [--format=<format>]

Shows all translations linked to a post.

Example:

$ wp perflocale translations list 42
+----------+---------+--------------------+---------+
| Language | Post ID | Title | Status |
+----------+---------+--------------------+---------+
| EN * | 42 | Hello World | publish |
| FR | 160 | Bonjour le monde | publish |
| DE | 165 | Hallo Welt | publish |
+----------+---------+--------------------+---------+

The * marks the current post's language.

Create Translation

wp perflocale translations create <post_id> --to=<lang>

Creates a new translation post (copies content from source).

Example:

$ wp perflocale translations create 42 --to=fr
Success: Translation created. New post ID: 200

Delete Translation

wp perflocale translations delete <post_id> --lang=<slug>

Permanently deletes a translation post. Prompts for confirmation.

Example:

$ wp perflocale translations delete 42 --lang=fr
Are you sure you want to proceed? Delete fr translation (post 200)? [y/n] y
Success: Translation deleted (post 200).

Set Language

wp perflocale translations set-language <post_id> --lang=<slug>

Changes the language of an existing post. Fails if the language is already used by a sibling in the same translation group.

Example:

$ wp perflocale translations set-language 42 --lang=en
Success: Post 42 language set to en.

$ wp perflocale translations set-language 42 --lang=fr
Error: Failed to set language. The language may already be used by a sibling translation.

Strings

Scan for Strings

wp perflocale strings scan [--domain=<domain>] [--path=<path>]

Scans PHP files for translatable strings (__(), _e(), _x(), _n(), _nx(), _n_noop()).

Options:

  • --domain=<domain> - Only scan strings for a specific text domain.
  • --path=<path> - Directory to scan. Default: active theme directory.

Examples:

# Scan active theme
$ wp perflocale strings scan
Scanning /var/www/html/wp-content/themes/flavor/flavor...
Success: Found 342 strings, inserted 15 new.

# Scan a specific plugin
$ wp perflocale strings scan --path=/var/www/html/wp-content/plugins/woocommerce --domain=woocommerce
Scanning /var/www/html/wp-content/plugins/woocommerce...
Success: Found 4821 strings, inserted 4821 new.

Performance:

  • Batched inserts (500 per batch) - handles large codebases.
  • Skips files over 2 MB to prevent memory exhaustion.
  • Excludes vendor/, node_modules/, .git/, tests/, build/, dist/.

Slugs

Backfill Slug Translations

wp perflocale slugs backfill

Populates the slug translation table for all existing term translation groups. This ensures that translated taxonomy URLs work correctly.

When to run:

  • After migrating from another multilingual plugin.
  • After creating term translations manually.
  • If taxonomy archive URLs show 404 errors.

Example:

$ wp perflocale slugs backfill
Success: Backfilled 48 slug translation entries.

Verify Slug Translations

wp perflocale slugs verify

Checks if all terms in translation groups have corresponding slug translation entries.

Example:

$ wp perflocale slugs verify
Success: All term translations have slug entries.

$ wp perflocale slugs verify
Warning: 12 terms are missing slug translations. Run 'wp perflocale slugs backfill' to fix.

Cache

Flush Caches

wp perflocale cache flush

Flushes all three cache layers:

  • L1: In-memory static cache.
  • L2: WordPress object cache (Redis/Memcached if available).
  • L3: Transients (wp_options table).

Example:

$ wp perflocale cache flush
Success: All PerfLocale caches flushed.

Migrate

Migrate from another multilingual plugin

wp perflocale migrate <source> [--dry-run] [--yes]

Imports translation data from another multilingual plugin into PerfLocale’s own tables. The source plugin’s data is not modified or deleted - the importer is read-only on the source side and writes new rows on the PerfLocale side.

Arguments:

  • <source> (required) - one of wpml, polylang, translatepress.

Options:

  • --dry-run - confirm the source is detected and importable without writing anything.
  • --yes - skip the interactive “Are you sure?” prompt (use for scripting / CI).

Examples:

# Confirm WPML data is detected.
$ wp perflocale migrate wpml --dry-run
Dry run - checking wpml data...
Success: Wpml data detected and ready to import. Run without --dry-run to proceed.

# Run the real import, prompt for confirmation.
$ wp perflocale migrate wpml
Migrate translation data from wpml? This cannot be undone. [y/n] y
Migrating from wpml...
Success: Migration complete. Imported: 234 posts, 89 terms, 1412 strings.

# Scripted (no prompt).
$ wp perflocale migrate polylang --yes
Migrating from polylang...
Success: Migration complete. Imported: 128 posts, 34 terms.

Per-source guides: WPMLPolylangTranslatePress. For the shared pre-flight steps and safety model, see the migration overview.

Database Migrations

Run pending schema migrations

wp perflocale db-migrate

Applies any pending PerfLocale database schema migrations. Idempotent - safe to run multiple times. Useful in CI/CD pipelines or headless environments where the WordPress admin dashboard is never visited (since the migrator normally runs on admin_init).

Example:

$ wp perflocale db-migrate
Success: PerfLocale database migrations completed successfully.

Health Check

Run Database Integrity Checks

wp perflocale health-check [--fix]

Checks for database inconsistencies and optionally repairs them.

Options:

  • --fix - Automatically fix found issues.

Checks performed:

  1. Orphaned post links - Translation links pointing to deleted posts.
  2. Orphaned term links - Translation links pointing to deleted terms.
  3. Invalid language references - Links referencing deleted languages.
  4. Widow translation groups - Non-string groups with zero remaining links. String-type groups are preserved (they are valid with no links until a translation is saved).
  5. Groupless orphan links - Translation links whose parent group row no longer exists.

Since 1.0.16, --fix delegates to the shared cleanup_orphans() method on the translation-group repository, so the CLI and the internal sweep produce identical results. Running without --fix is strictly read-only.

Examples:

# Report only
$ wp perflocale health-check
Running PerfLocale health checks...

	Orphaned post links: 0
	Orphaned term links: 3
	Invalid language references: 0
	Widow translation groups: 5
	Groupless orphan links: 2

Warning: Found 10 issues. Run with --fix to repair.

# Auto-fix
$ wp perflocale health-check --fix
Running PerfLocale health checks...

	Orphaned post links: 0
	Orphaned term links: 3
	Fixed: removed 3 orphaned term links.
	Invalid language references: 0
	Widow translation groups: 5
	Fixed: removed 5 widow groups.
	Groupless orphan links: 2
	Fixed: removed 2 groupless orphan links.

Success: Fixed 10 issues.

Status

Translation Completeness Overview

wp perflocale status [--format=<format>]

Displays translation completeness per language.

Options:

  • --format=<format> - Output format: table (default), json, csv.

Example:

$ wp perflocale status
+---------------------+-----------+-------+-------+-------+
| Language | Published | Draft | Empty | Total |
+---------------------+-----------+-------+-------+-------+
| English (en) | 12 | 2 | 0 | 14 |
| French (fr) | 14 | 0 | 0 | 14 |
| German (de) | 8 | 1 | 5 | 14 |
| Arabic (ar) | 3 | 0 | 11 | 14 |
+---------------------+-----------+-------+-------+-------+

$ wp perflocale status --format=json
[{"Language":"English (en)","Published":12,...}]

Scripting Tips

Suppress Confirmation Prompts

Use --yes to skip all confirmation prompts (useful in scripts and CI):

wp perflocale languages delete fr --yes
wp perflocale translations delete 42 --lang=fr --yes

Combine with WordPress CLI

# Translate all published pages to German
wp perflocale translate --all --to=de --post-type=page --skip-existing

# Check health and fix issues
wp perflocale health-check --fix

# Full maintenance routine
wp perflocale cache flush && wp perflocale slugs backfill && wp perflocale health-check --fix

JSON Output for Parsing

# Get languages as JSON for scripting
wp perflocale languages list --format=json | jq '.[].Slug'

# Get translation status as JSON
wp perflocale status --format=json | jq '.[] | select(.Published < .Total)'