Machine Translation

Translate content instantly with leading MT providers, then refine with human review.

🇺🇸 English “Welcome to our bakery — we bake fresh bread daily.”
🇩🇪 Deutsch via DeepL · best for European languages
“Willkommen in unserer Bäckerei — wir backen täglich frisches Brot.”
Lossless switch Swap providers anytime — existing translations stay in your Translation Memory.

Multiple Providers

Connect to DeepL, Google Translate, Microsoft Translator, or self-hosted LibreTranslate. Switch providers anytime without losing existing translations.

Welcome to our bakery

We bake fresh sourdough every morning — come and try our award-winning artisan loaves.

Translate to
Drafts queued Translations land as drafts — ready for human review.
  • Deutsch empty
  • Français empty
  • Español skipped

Auto-Translate on Publish

When you publish or create content, PerfLocale automatically sends it for machine translation. Results are saved as drafts for human review.

Translation Glossary admin with Add New Term form and a list of terms like Acme Bakery, cold ferment, sourdough mapped per language pair
Brand and product names stay locked across every language pair

Glossary and Translation Memory

Define terms that should always be translated a specific way. Previously translated segments are reused automatically, reducing API calls and improving consistency. TM segments are stored locally with no user IDs or IP addresses attached, and the GDPR Erase Personal Data flow scrubs a data subject’s identifiers out of both source and target text on request — see Privacy & GDPR.

Monthly character budget
100,000 chars/month · resets in 12 days
47%
47,200 used 52,800 remaining
Auto-stops at 100% — no overage charges.
Per-user hourly cap
Throttles runaway scripts before they spend
500/hour
  • Editor OK
    234 / 500 chars this hour
  • runaway-script.php throttled
    500 / 500 chars · further requests blocked for 47 min
Filterable per role/user via perflocale_mt_hourly_cap
All provider API calls use encrypted connections.

Usage Controls

Set monthly character limits to control API costs. PerfLocale tracks usage and stops when the limit is reached. All API calls use encrypted HTTPS connections. A per-user hourly cap (500/hour by default, filterable) protects your budget from runaway scripts.

Scan results
47 posts scanned · 3 pending
Auto
  • Sourdough Starter ×42 product
    …our Sourdough Starter ferments for 18 hours…
  • Acme Bakery ×28 brand
    …visit Acme Bakery on Devon High Street…
  • Devon Mill ×15 proper noun
    …flour milled at the historic Devon Mill
REST API GET /wp-json/perflocale/v1/glossary/candidates

Auto-Glossary Scanner

Scan published content to discover candidate glossary terms - brand names, product names, repeated proper nouns - that you’ll want translated consistently. Review and accept candidates with one click. Available via the Glossary REST API for automation.

POST /translation-memory/suggest
{
  "source": "Add to basket",
  "locale": "de_DE",
  "limit": 5
}
200 OK 4 matches · ranked by similarity + usage
  • “Add to basket” “In den Warenkorb”
    100% ×142 exact
  • “Add to cart” “In den Warenkorb”
    85% ×38 fuzzy
  • “Add item” “Artikel hinzufügen”
    72% ×12 fuzzy
  • “Place order” “Bestellen”
    60% ×7 fuzzy
Use it for Custom editors · external review tools · CI pipelines

Fuzzy Translation-Memory API

Query the TM store programmatically: POST /translation-memory/suggest returns exact + fuzzy matches ranked by similarity and usage count. Use it to power custom editors, external review tools, or CI pipelines. See the REST reference.

WordPress block editor with a paragraph block selected; the PerfLocale toolbar dropdown is open showing 'Translate to English (UK)', 'Translate to German', 'Translate to French', 'Translate to Spanish', 'Translate to Arabic', plus 'Translation Memory suggestions', 'Wrap in Show If Language', and 'Mark Do not translate'.
In the standard Gutenberg toolbar — no separate translation panel

Block Editor Integration

A PerfLocale dropdown in the Gutenberg block toolbar for paragraph, heading, quote, list item, button, and code blocks. Four actions on the selected block:

  • Translate with MT - send the block to any target language without leaving the editor. Backed by POST /block-translate.
  • Translation Memory suggestions - search your TM for exact and fuzzy matches and apply one with a click.
  • Wrap in “Show If Language” - turn the block into a language-conditional section in two clicks.
  • Mark “Do not translate” - flag the block as untranslatable; machine-translation preserves it verbatim and emits data-perflocale-skip="1" on the rendered HTML.
WordPress AI Client WP 7.0+
// Pick "WordPress AI Client" in
// PerfLocale → Settings → Machine Translation.
// PerfLocale routes every translation through
// whatever AI provider the host has wired up
// (OpenAI, Anthropic, local Ollama, …)
// — no new API key, no per-vendor settings.

// Override per-request:
add_filter(
  'perflocale/mt/wp_ai_client_args',
  fn( array $a ) => array_merge(
    $a,
    [ 'provider' => 'anthropic',
      'model'    => 'claude-opus-4-7' ]
  )
);

WordPress AI Client Provider (WP 7.0+)

On WordPress 7.0 and later, the new WordPress AI Client provider delegates translation to whatever AI provider the host site already has configured under core's AI Client abstraction. No second API key, no separate billing dashboard — your translations and your other AI features share one provider.

The provider is feature-detected: it only appears in the dropdown when wp_ai_client() (or a custom resolver registered via perflocale/mt/wp_ai_client_resolver) is available. The plugin's placeholder masker still gates every response so brand names and printf tokens survive the round trip — same integrity guarantee as DeepL / Google / Microsoft.

LLM-driven translation often handles idioms, register, and brand voice better than dedicated MT engines for marketing and long-form content; it's slower per call but reuses the AI quota you already pay for. See the WP 7 hooks reference for prompt, args, and capability filters.

MT Quality Scoring opt-in
$ wp cron event list --hook=perflocale_mt_quality_score

next_run         schedule
+15 min          hourly

# After one tick (default sample_size=50):
SELECT review_score, COUNT(*)
FROM wp_perflocale_string_translations
WHERE review_score IS NOT NULL
GROUP BY review_score;

review_score | COUNT(*)
-------------+---------
           5 |      32
           4 |      12
           3 |       4
           2 |       2   ← flagged for review
           1 |       0

MT Quality Scoring (WP 7.0+, opt-in)

An hourly background job samples machine-translated rows from string_translations and translation_links, asks the active AI provider to rate them 1–5 against the source, and writes the score back to the row. Low scorers get a “needs review” badge in the Strings and Translations admin views, so a human reviewer can prioritise the translations most likely to need a second pass instead of reading every row.

The default threshold flags scores ≤ 2. The whole feature is gated behind an explicit setting AND auto-detection of an AI-capable provider — it never runs by accident, and never on installs that lack an AI client. Cost is bounded: sample size, table coverage, per-row skip, and the prompt itself are all filterable. See the sample_size, tables, skip_row, prompt, and persist action hooks.

WordPress Connectors API WP 7.0+
// Already entered your DeepL key in
// another plugin's Connector?
// PerfLocale picks it up automatically.

// Priority chain:
//   1. environment variable
//   2. PHP constant (wp-config.php)
//   3. WordPress Connectors API   ← new
//   4. database (admin form)

// Extend to non-MT keys:
add_filter( 'perflocale/connectors/slug_map',
  fn( array $m ) => array_merge( $m, [
    'geo_ipstack_key' => 'ipstack',
    'wc_oxr_api_key'  => 'openexchangerates',
  ] )
);

Connectors API key sharing (WP 7.0+)

When WordPress 7.0's Connectors API is present, PerfLocale resolves MT API keys (DeepL, Google, Microsoft, LibreTranslate) through Connectors first — before falling back to the database value. Users who've already registered their key in another plugin's connector reuse it without re-typing, and rotation happens in a single place.

Source priority stays predictable: environment variable > PHP constant > Connectors API > database. Empty connector values are treated as “not set” so an explicitly-defined-but-empty connector doesn't shadow a real DB value. The map of which setting goes to which connector slug is filterable, so geo / currency / webhook keys can opt in too.

← Back to Features