I got a frantic call from a client with a big multilingual WooCommerce site. Their marketing head in the UK decided to A/B test some button text, changing “Proceed to Checkout” to “Confirm and Pay.” A tiny, sensible change. Except it wasn’t. The moment they hit save, the German, French, and Spanish versions of that button broke, reverting to the new English text. Total nightmare. Their support tickets lit up. The problem isn’t the client; it’s the default way WordPress handles translations.
See, WordPress uses the literal string—”Proceed to Checkout”—as the lookup key. So when the key changed, all the connections to the existing translations were severed. This is a huge, fragile flaw if you’re running a serious site. You can’t have a content editor accidentally breaking localization for three other languages. This is where using WordPress translation placeholders, an idea I saw detailed over at carlalexander.ca, becomes essential.
Why Your Translation Method Is Brittle
My first, cynical thought was to tell the client’s team, “Here’s a list of strings you are forbidden to edit. Ever.” But that’s not a solution. That’s just me being a difficult developer. It creates friction and stops the marketing team from doing their job. A developer’s job is to build robust systems, not to tell people “you’re holding it wrong.”
The real fix is to stop using the display text as the identifier. Instead of this:
_e( 'Confirm and Pay', 'my-text-domain' );You use a stable, unchanging key. A placeholder. Like this:
_e( 'checkout.payment_button', 'my-text-domain' );This key, checkout.payment_button, never changes. Now the marketing team can edit the English translation of that key from “Confirm and Pay” to “Buy Now!” and it won’t affect the German version one bit. Problem solved, right?
Almost. Here’s the kicker: if a translation doesn’t exist for a given language, WordPress will just print the raw key. A user might see “checkout.payment_button” on the frontend. Not good. We need a reliable fallback.
The Right Way: Forcing a Fallback Locale
This is the part that feels like a clever hack but is actually the proper way to do it. You need to create a complete English (en_US) translation file for your plugin, mapping your keys to their English values. Then, you force WordPress to use this file as the ultimate default for your plugin’s text domain. You can do it with a simple filter.
/**
* Enforces the 'en_US' locale for our plugin's text domain.
*
* This ensures that even if a translation is missing for the site's
* current language, we fall back to our English strings instead of
* showing the raw placeholder keys.
*
* @param string $locale The locale for the given domain.
* @param string $domain The text domain.
* @return string The modified locale.
*/
function myplugin_enforce_default_locale( $locale, $domain ) {
if ( 'my-text-domain' === $domain ) {
// Here's the magic. We just force it to American English.
return 'en_US';
}
return $locale;
}
add_filter( 'plugin_locale', 'myplugin_enforce_default_locale', 10, 2 );With this filter in place, if WordPress is running in German (de_DE) and can’t find a translation for checkout.payment_button in your German `.mo` file, the `plugin_locale` filter kicks in for your text domain. It tells WordPress, “Fine, just use the `en_US` file for this one string.” The user sees proper English text instead of a broken key. And that was it.
So, What’s the Point?
Using translation placeholders isn’t the default WordPress way, but it’s the professional way. It separates the concerns of content and code, making your plugin or theme far more resilient to the realities of a living, breathing website where content changes.
- It’s Stable: Content editors can no longer break translations by fixing a typo.
- It’s Clearer: A key like
admin.error.api_key_invalidgives you far more context than just seeing the string “An error occurred.” - It’s Maintainable: It protects your international users from seeing broken text and protects you from emergency support calls.
Look, this stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.
Leave a Reply