Machine Translation
Translate content instantly with leading MT providers, then refine with human review.
Multiple Providers
Connect to DeepL, Google Translate, Microsoft Translator, or self-hosted LibreTranslate. Switch providers anytime without losing existing translations.
We bake fresh sourdough every morning — come and try our award-winning artisan loaves.
- 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.

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.
- Editor OK
- runaway-script.php throttled
perflocale_mt_hourly_capUsage 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.
- 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…
GET /wp-json/perflocale/v1/glossary/candidatesAuto-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.
/translation-memory/suggest{
"source": "Add to basket",
"locale": "de_DE",
"limit": 5
}- “Add to basket” “In den Warenkorb”
- “Add to cart” “In den Warenkorb”
- “Add item” “Artikel hinzufügen”
- “Place order” “Bestellen”
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.

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.
// 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.
$ 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 | 0MT 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.
// 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.