Change Any WooCommerce Text Without a Translation File
You want “Select options” to say “Choose your size” on your variable products. Or you want “Place order” to be “Pay Now” at checkout. The standard advice is to generate a translation file, edit it in Poedit or Loco Translate, compile a .mo file, and override the WooCommerce text domain. That’s a lot of moving parts for what should be a 30-second change.
WordPress fires a gettext filter for every translatable string before it’s displayed. You can hook in, match the exact string you want to swap, and return a different one. No .mo file, no plugin, no compile step. The snippet below shows a complete pattern with multiple strings and multiple text domains.
/**
* Replace WooCommerce text strings without editing translation files.
*
* Each case statement maps the original English string to your replacement.
* Add as many cases as you need. Match the original text exactly,
* including punctuation and capitalization.
*/
add_filter('gettext', 'carticy_replace_woocommerce_strings', 20, 3);
function carticy_replace_woocommerce_strings($translation, $original, $domain)
{
// Only process the text domains we care about
if ($domain !== 'woocommerce') {
return $translation;
}
switch ($original) {
case 'Select options':
$translation = __('Choose your size', 'woocommerce');
break;
case 'Add to cart':
$translation = __('Add to bag', 'woocommerce');
break;
case 'Place order':
$translation = __('Pay Now', 'woocommerce');
break;
case 'Related products':
$translation = __('You might also like', 'woocommerce');
break;
}
return $translation;
}
The match must be exact. “Add to cart” with a capital A is different from “add to cart”. “Select options” with the trailing period (which appears in some WooCommerce versions) is a different string. If your change isn’t taking effect, the string you’re trying to match is probably not the one being passed through the filter. Use WP_DEBUG, log $original for the page you care about, and you’ll see the exact strings to target.
Pluralized Strings Need a Different Filter
Strings like “1 item” vs “5 items” go through ngettext instead of gettext. If the text you want to change includes a quantity, hook the plural filter too.
add_filter('ngettext', 'carticy_replace_woocommerce_plurals', 20, 5);
function carticy_replace_woocommerce_plurals($translation, $single, $plural, $number, $domain)
{
if ($domain !== 'woocommerce') {
return $translation;
}
// Match against the singular form even when displaying plural
switch ($single) {
case '%s item':
$translation = ($number === 1) ? '%s product' : '%s products';
break;
}
return $translation;
}
Multiple Text Domains
WooCommerce itself uses the woocommerce domain, but premium WooCommerce extensions usually have their own. WooCommerce Subscriptions uses woocommerce-subscriptions. WooCommerce Wholesale Prices Premium uses woocommerce-wholesale-prices-premium. If you want to change a string from one of those, swap the domain check or expand it to a list.
/**
* Same idea, but handling multiple text domains.
*/
add_filter('gettext', 'carticy_replace_multi_domain_strings', 20, 3);
function carticy_replace_multi_domain_strings($translation, $original, $domain)
{
$supported_domains = array('woocommerce', 'woocommerce-subscriptions');
if (!in_array($domain, $supported_domains, true)) {
return $translation;
}
if ($domain === 'woocommerce') {
switch ($original) {
case 'Select options':
$translation = 'View product';
break;
}
} elseif ($domain === 'woocommerce-subscriptions') {
switch ($original) {
case 'Sign up':
$translation = 'Start subscription';
break;
}
}
return $translation;
}
Performance Considerations
The gettext filter fires hundreds or thousands of times per page render. Keeping the function lean matters. The early-return on text domain is essential: if you remove it, every translated string from every plugin and theme runs through your switch, which is slow. The switch statement itself is O(1) for the matched case and very fast even with many cases. Avoid putting expensive operations inside (database queries, regex, file I/O); stick to simple string comparison.
Verification
- Add the snippet to your child theme’s
functions.phpor a custom plugin - Pick a string from the snippet (e.g. “Add to cart”) and visit a product page
- Confirm the button text now shows the replacement (e.g. “Add to bag”)
- Try a string that isn’t in the switch and confirm it displays unchanged
- Switch the site language temporarily and confirm only the strings you targeted change, not other translations
Need Help?
Learn how to add custom code to WordPress or reach out for custom development help.
About the Author
More Code Snippets
-
Reorder the Columns on the WooCommerce Orders List
Put your WooCommerce orders list columns in whatever order works…
-
Set the Default Country on WooCommerce Checkout
Pre-fill the WooCommerce checkout country (and optionally state) dropdown with…
-
Bulk Delete Expired Unused WooCommerce Coupons (Batched, Safe)
One-time bulk cleanup utility for stores with thousands of expired,…