Migrating from Polylang

PerfLocale’s Polylang importer reads the post_translations and term_translations taxonomies and rebuilds your translation groups as native PerfLocale rows. Polylang’s data is read-only during the import - nothing is touched in its tables.

If you haven’t already, start with the migration overview for the shared pre-flight steps (backup, install PerfLocale, add languages).

What’s imported

  • Post translations - Polylang stores translation groups as serialised PHP arrays in the description field of each post_translations term. The importer unserialises those, looks up each post by ID, and rebuilds the group in PerfLocale.
  • Term translations - same approach with the term_translations taxonomy: categories, tags, and any custom taxonomies Polylang was tracking.

What’s not imported

  • String translations. The Polylang importer only handles posts and terms. If you use Polylang String Translations (the companion plugin or pro addon) for theme/plugin UI strings, those aren’t carried over. After the migration, scan the site with wp perflocale strings scan to rebuild the string catalogue, then translate the strings again in the PerfLocale admin. For most sites this is a handful of strings, but budget time for it.
  • Menus & widgets. Polylang uses a different mechanism for menu / widget language-scoping (per-location menu variants). PerfLocale’s menu model is translation-group based, so menus need to be rebuilt post-import.
  • Language-switcher widget configuration. Polylang’s widget settings don’t carry across - configure PerfLocale’s Language Switcher block, widget, or shortcode from scratch.
  • Custom language flags and display names. Re-add them in PerfLocale → Languages when you create the matching PerfLocale language.

Pre-flight checks

Polylang doesn’t have to be active

The importer works both with Polylang active and with Polylang deactivated. Detection is two-layered:

  1. If the language taxonomy is registered (Polylang is active), the importer uses it.
  2. If Polylang is deactivated but its data remains in the database (language terms in wp_term_taxonomy), the importer detects that and proceeds anyway.

Practically: if you already switched off Polylang, the migration still works. You can activate it again to ease verification, or leave it off - either is fine.

Match your language codes

The importer maps Polylang’s language slug (e.g. fr, de) to a PerfLocale language using:

  1. Exact slug match first.
  2. Locale-prefix fallback: PerfLocale’s locale starts-with Polylang’s slug (e.g. PerfLocale fr_FR matches Polylang fr).

If your Polylang install used full locale slugs like en_gb, add a PerfLocale language with the matching slug exactly. Unmatched languages are reported as warnings (“No PerfLocale language match for Polylang slug ”) and their content is skipped.

Run the import

From the admin

  1. Go to PerfLocale → Settings → Export & Import.
  2. Scroll to “Import from Polylang”. If the button isn’t shown, Polylang data wasn’t detected - the language taxonomy doesn’t exist and there are no language terms in the DB.
  3. Click Import from Polylang. Confirm the prompt.
  4. On completion the page reloads with a count of posts and terms imported.

From WP-CLI

# Confirm Polylang data is detected.
wp perflocale migrate polylang --dry-run

# Run the real import (prompts for confirmation).
wp perflocale migrate polylang

# Skip the prompt when scripting.
wp perflocale migrate polylang --yes

Verification

  1. Post counts match. Compare the post-translation counts reported by the importer against your expected counts (Polylang’s admin → Languages tab shows totals per language).
  2. Spot-check a post. Open any multilingual post. The PerfLocale sidebar should list every language that had a translation in Polylang.
  3. Check terms. Confirm translated categories / tags are linked in the PerfLocale translation column.
  4. Visit translated URLs. Polylang’s URL prefix convention (e.g. /fr/) is matched by PerfLocale’s default slug-based prefix, so existing URLs should continue resolving. Browse a handful and confirm they render the right language.
  5. Rebuild strings. If you used Polylang String Translations, run wp perflocale strings scan --target=theme and --target=plugins, then work through PerfLocale → Strings to re-translate them.

Re-running the import

The importer is idempotent. For each Polylang translation term, it looks for an existing PerfLocale group that already contains any of the posts listed - if found, it reuses the group and adds missing siblings. Already-linked siblings at the same language/group are skipped. If your first run warned about a language you hadn’t added yet, add it and re-run; the new language’s content fills in without duplicating the rest.

Rollback

No automatic rollback. The safe paths:

  • Restore from backup - the cleanest undo.
  • Reactivate Polylang - Polylang’s data is untouched, so reactivating restores its behaviour. PerfLocale’s newly-created translation groups will sit alongside Polylang’s without interfering (PerfLocale only acts when its own data is present and the plugin is active).

Troubleshooting

“Polylang language taxonomy not found”

Either Polylang was never set up on this site, or its data was deleted. Check for language rows in wp_term_taxonomy: SELECT COUNT(*) FROM wp_term_taxonomy WHERE taxonomy = 'language';. If the count is zero, there’s nothing to migrate.

The import timed out

Switch to WP-CLI. Admin-UI requests are bounded by PHP’s request timeout; WP-CLI isn’t.

My translated strings didn’t come across

Expected - the Polylang importer doesn’t handle strings. See “What’s not imported” above.

Next steps