So you've found the perfect plugin: it has all of the functionality you need, it's within your budget, and there's surprisingly awesome support. Great – but what if you need to change just one little line of text? What if you want to do something simple like change “Add to Cart” to “Add to Basket”? Or change “Related Products” to “See these related products”?
If you're lucky there's a filter for that particular string but sometimes there isn't. Then what do you do?
Codestyling Localization
You could certainly use something like Codestyling Localization which is nice for people who has no coding ability but do you really want to have to edit the .po file every time a new version of the plugin comes out? Of course not.
Cue the gettext Filter
This is where the incredibly useful gettext filter comes in. If you take a peek at your plugin's code you'll see strings like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php _e( 'Related Products', 'woocommerce' ); ?> |
You can easily translate these strings by adding a filter to your functions.php file:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Change text strings | |
* | |
* @link http://codex.wordpress.org/Plugin_API/Filter_Reference/gettext | |
*/ | |
function my_text_strings( $translated_text, $text, $domain ) { | |
switch ( $translated_text ) { | |
case 'Related Products' : | |
$translated_text = __( 'Check out these related products', 'woocommerce' ); | |
break; | |
} | |
return $translated_text; | |
} | |
add_filter( 'gettext', 'my_text_strings', 20, 3 ); |
Easy huh? You can add as many translations to that filter as you need.
Final Result
With just 15 lines of code I was able to translate several strings on the WooCommerce single product page.
After seeing these examples do you have any doubt that the gettext filter is one of WordPress' most useful functions?
Image credit: Wikiepedia.org
Awesome work on this Patrick! Needed help changing the labels in WooCommerce from products to items and this solved my needs perfectly! Thanks again!
Thanks James! Glad it worked out for you. 🙂
Really useful post Patrick, thanks! It will be useful to change some of the WooCommerce text strings that seem badly worded or out of place on my particular site. It would be useful if you could modify your example code above to show how two or more text strings can be changed. I guess extra ‘cases’, but not sure of the exact syntax.
Cheers, James 🙂
Did you see the “15 lines of code” link above? That example includes 3 different strings in the one function. I hope that helps! 🙂
Cool Patrick, thanks. I hadn’t seen the ’15 lines of code’ link previously, but I have now and it works perfectly. This is such a useful bit of code!!!
So this was working merrily until updating wordpress I believe.. or perhaps it was another plugin but since then – http://grab.by/s7Bq
I’ve had to disable the functions until I figure out what is causing it.. any ideas?
You should always return the translated text. You’ll need to pull the $translated_text outside of the if conditional. I hope that helps! 🙂
That was it! Thanks again Patrick!
Silly mistake…
Hey Patrick.
Thanks for sharing! That’s something I looked for a while.
I took a look at the WP Codex. It says:
” IMPORTANT: This filter is always applied even if internationalization is not in effect, and if the text domain has not been loaded. If there are functions hooked to this filter, they will always run. This could lead to a performance problem.”
So did you fell any performance issue???
Cheers
Hey Martin, no performance issues my side. The key here is if you have performance issues.
If you mean: performance issue on your website? Nop. 🙂
I meant it generally. Maybe on another website.
Although I’m thankful for your post, I will stay on editing the strings via .po and .mo files.
For those who want to know:
I use the woocommerce-en_GB.mo and woocommerce-en_GB.po files.
I moved these files from woocommerce/i18n/languages to to wp-content/languages/woocommerce/. Important: MOVE not copy, or nothing will happen. 🙂
This place is upgrade safe (see http://docs.woothemes.com/document/woocommerce-localization/).
Then I download these files on my computer. Editing happens with the programm “Poedit”. Saving those files. Uploading again.
One last important change in the wp-config.php file: define(‘WPLANG’, ‘en_GB‘);
So WP knows, which translation it loads.
And done. 🙂
I been on it for 4 days now and your note on MOVING and not just copying finally did the trick. Can’t thank you enough sir 😀
Cheers. Sammy
Beyond thanks man! It works like a charm.
Hi,
Cool code is there a way to limit this to change a string only on say the single product page. Other places I want it to stay the same.
This is certainly possible. You’ll have to look into is_single() & get_post_type(). I hope that helps! 🙂
This is great! I was using some complicated way to achieve the same thing that was just a pain to use – this is too easy. Thanks Pat!
very cool. Any clue how I could further the awesomeness by changing “Check out these related products” to be something different for different categories of products?
You could do something like this using the
is_product_category()
function in a conditional to create different translations. See the WooCommerce Conditional Tags page for some examples.Yep – thats probably gonna do it! Problem, I’m a noob when it comes to actually coding in these filters, and I am using your “15 lines of code” gist to modify and work for my site…and it works well. Where in there would I add this “is_product_category( ‘shirts’ )” code?
Thanks for the patiences and help!
I’m working on some big projects right now (one of which will be announced in the next week or so!) so I can’t work on it. Try using Codeable. They do really great work.
Noob too here. So this comment section is helping a lot. Thanks, fellas!
I think that you should not include such a function call. Just put in the strings you want to change.
Hi Patrick or anyone who can help.
I need to change “Sign-up fee” text in WooCommerce Subscriptions. The text is misleading for what I’m trying to do and I need to get that sorted like yesterday. It’s killing the launch of our site. I’m very green to all this and need to know where these files are on the server normally and where in the php do I need to add this code which is talked about in this post.
I would be really great full if someone can help
Hey Oriche,
Have you looked into the
woocommerce_subscriptions_product_price_string
filter? You can see an example of someone using that filter on Stack Overflow. That should get you 80% of the way there. A developer will have to customize the string for you.As per usual I recommend Codeable.
Great help, thanks Patrick! Do you know any way to insert a Font Awesome icon next to translated text… right now it just shows the icon text, not icon. ie
case 'Place order' :
$translated_text = __( '<i></i> Buy Now', 'woocommerce' );
break;
Not sure if it’s the code formatting in the comment that’s messed up here but do you have a class in your
i
tag? And does that class actually show up in the source code on the front end?Hey Patrick
This was a great help to me last year and I changed a couple of strings really easily for me and my site. But yesterday I updated the site to WordPress 4.0 & WooCommerce 2.2.4 and now the strings are not working – the labels I previously had changed are back to normal!
Any suggestions gratefully received 🙂
Hey Andy,
Most likely the strings have changed in some small way. I’d go through the source code and make sure they’re the exact same. The
gettext()
filter hasn’t gone anywhere.Thanks for the reply Patrick thats good to know 🙂 So any idea what file the strings are stored in for the WooCommerce Cart page? Its been a while since I last looked at this! I guess probably cart.php or something similar?
Oddly, using your code for gettext() didn’t work, yet the following did?
add_filter('gettext', 'translate_text');
add_filter('ngettext', 'translate_text');
function translate_text($translated) {
$translated = str_ireplace('SHIP TO A DIFFERENT ADDRESS?', 'DELIVER TO A DIFFERENT ADDRESS?', $translated);
return $translated;
}
This came from: https://support.woothemes.com/hc/en-us/articles/202974056-How-to-remove-From-text
Using str_ireplace() is very inefficient here as the translate_text() function is called a high number of times for each page load.
I suggest a simple string comparison and replacement.
http://pastebin.com/Gqgr0Njk
FYI: I did a test on a new installation of WordPress 4.0. I logged each time the ‘gettext’ filter (not ‘ngetext’) was called.
For one admin page it was called 1003 times. On the home page of the site it was called 516 times. So, the function needs to be very efficient to minimise page load impact.
This was extremely helpful. The gettext page on the codex is a bit abstract so I’m glad I found an example of how to put it to real life use – and with Woo Commerce which I’m recently getting into! Thanks for the tips!
Looks like this is only helpful if your website is only in one language. Or could you make a differentiation between to languages with this filter?
This would make woocommerce templates / wordpress templates customizing more flexible.
WordPress out of the box only supports one language at a time. You would have to install WPML or a similar plugin to have multiple languages. Regardless, you should be able to translate “Carrito” which means cart in Spanish to “Bolsa” which means bag. You can then do the same for any other languages.
I was wondering if it would be possible to change all occurrences of the word
Product
toItem
sitewide, even if this is just part of a string? Of course we could filter all strings that include this word, but that would take a lot of code. So would it be possible too, to change this word in every string that includes it with fewer lines of code with the gettext filter?You could use the gettext filter to do this but it would be very taxing. You would have to write a regular expression and run every single string on the page through it. I would instead write out the code to replace every string line by line. Tedious but not as much of a strain on your site.
Thanks for your reply Patrick! Setting lines of code for every single string to get better site performance as a result is absolutely worth it in my opinion then. Thanks again!
Hello,
I am using WPML and i was not able to change strings with
gettext
filter. I want to change allproduct
words withticket
. How can I set lines of code? I have very little code knowledge.Hey Akif,
I’d guess that WPML is preventing this somehow. I’d reach out to them and see if they can help you with this. Short of that it’ll probably have to be custom developed.
Hi Akif, I am also using WPML and it works fine for me. Maybe you mistyped part of the code?
Hi Emiel, it is interesting, i am using adrenalin theme (commercegurus) and it didn’t work. Could you give me the code that you used? I put it on my child theme’s functions.php file, is it the right location?
Hi Akif, the child theme’s funtions.php is the correct file to place the code in.
Here’s the code that should work for you too:
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Product' :
$translated_text = __( 'Ticket', 'woocommerce' );
break;
}
return $translated_text;
}
add_filter( 'gettext', 'my_text_strings', 20, 3 );
Regards, Emiel.
Yes, It works! Thanks a lot!
Best Regards, Akif
I am using WPML also, and have added on the category product pages a text on english
Read more ->
that appears after each category product. But, when switching to Swedish text I want the words to be translated intoLäs Mer ->
. WMPL does not catch this manually added text, but can I use a code snippet to translate this words between languages?Any help is appreciated.
Hey Peter,
I’m not really sure how the inner workings of WPML function. You should really reach out to them about how to use the gettext filter with their plugin.
@Peter: This can be done like this:
– Customize the original text using Patrick’s gettext filter.
– Find the original string in WPML and set tranalations to completed status.
– Find the customized string in your wp (child) theme text domain and translate it.
– Also set status to translation completed.
I customized many strings this way on my site, which are also translatable in WPML.
Let me know if it works for you too.
Thank you for this code snippet! I am a total WP beginner and don’t know how to use Poedit, so your solution is easier for me 🙂
It worked on everything but “Scroll to top”arrow that my theme has. When you hover over the arrow, it shows a bubble that says “To the top!”. I would like to translate this into German but your code didn’t work for this…any idea what I would need to do? I am using the Virtue theme from WordPress.org.
The code should work for just about anything really. It’s possible your theme hard coded that text without running it through the WordPress translation functions. That would make it impossible to translate. I’d reach out to the theme developer for help with this.
The ‘To the top!’ text is hard coded in the virtue/assets/js/plugins.js script.
This is from: jQuery Scroll to Top Control on dynamicdrive.com
Unfortunately as get_template_directory_uri() is used in lib/scripts.php to load the plugins.js script, you cannot override it in a child theme. Having said that, as scripts.php is loaded by functions.php using locate_tempate(), maybe you could copy scripts.php and plugins.js into a child theme directory and edit plugins.js.
As you say you are a WP beginner, this is getting complicated. I don’t have another solution.
Hello, is there any way to replace some word in text with link but only words dos not has link
ex:
hi my name is ahmed , go to my site
and replaceahmed
withstr_replace('ahmed', '<a>ahmed</a>' , 'text');
will be
hi my name is <a>ahmed</a>
,but the problem is if is run this function again i got this:
hi my name is <a><a><a>ahmed</a></a></a>
How do you fix this?
It’s possible that the gettext filter is being run multiple times over that text for some reason.
Adding a link like this to the text is not the right way to do this. Use the appropriate filter like the_content().
This is a HUGE help! Thank you is not enough! Bless you, Patrick!
Hi Patrick, what does the 20, 3 mean in the final line?
Hey Ron,
For our purposes the
20
and3
shouldn’t change at all.20
is the priority (when to run) and3
is the number of arguments to pass.Life saver! Thanks!
Hi Patrick,
I was wondering how can I use this filter in a multisite instal ?
So for example I have 2 domains or blogs under 1 multisite – Example.com and Example.com/one or blog id 1 and blog id 2 if you like.
If I need to change the “Related Products” label on blog 1 to “More Product Like This” and then to “Similar Products” on the blog 2.
How can I go about this ?
I’ve been trying to figure it out on my own, but just can’t get it working.
Hey Joe,
Honestly I haven’t had much experience with multisites. I would reach out to Codeable to tweak this for you.
You could use get_current_blog_id() but I think that calling this function for every gettext call will slow things down. I suggest creating a separate plugin for each blog and only activate the one you need on each blog.
Hey! Do you know of a way to get rid of the shipping method label in the customer’s billing email? I use only one shipping method through a plugin and I do not want customers to be confused when they see the shipping method on their billing email.
In other words I do not want, ” Shipping: $16.95 via Tree Table Rate” appearing on their billing email. I want just “Shipping: $16.95” to appear on their billing email.
Thank you!
There’s most likely a different filter you can use for that. I’d reach out to Codeable.
@Meleah: The ‘woocommerce_order_shipping_to_display_shipped_via’ filter might be the one:
$shipping .= apply_filters( ‘woocommerce_order_shipping_to_display_shipped_via’, ‘ ‘ . sprintf( __( ‘via %s’, ‘woocommerce’ ), $this->get_shipping_method() ) . ”, $this );
You should be able to return an empty string to blank it out.
Thanks for this excellent post Patrick. Was exactly what I needed.
More than 2 years on, this post seems to be the post that keeps on giving! 🙂
Thanks Patrick,
for anyone needing to get it to work on ‘You may also like…’ upsells text you have to include … in the code in place of the 3 dots. Like this:
case ‘You may also like…’ :
$translated_text = __( ‘Additional Product Options’, ‘woocommerce’ );
break;
ha caught out by html interpretting the hellip. I’ll explain again in long hand: thats replace the 3 dots with ampersand hellip semi-colon. Like this:
case ‘You may also like ampersand hellip semi-colon’ :
$translated_text = __( ‘Additional Product Options’, ‘woocommerce’ );
break;
Cheers Pete. Seem to remember spending hours trying to work this out a little while back!
To change this text it is probably more efficient to copy templates/single-product/up-sells.php to your theme directory (THEMEDIR/woocommerce/single-product/up-sells.php). Otherwise the code is being executed for every string, which can only slow your site down a bit.
EXCELLENT! Thank you so much for this post! I ran into this problem using Gravity Flow for Gravity Forms and searched around for any possible solution. I’ve been a Joomla developer for several years and like Drupal, there are Language Overrides built in for this very reason. I cannot believe WordPress doesn’t have this as a feature!!!! Especially since this post is now almost 3 years old.
Very useful. Thanks alot for the article worked like a charm
Patrick,
if your examples were inside of a plugin, would it be required for us to “unhook” gettext manually, or is wordPress able to do that on it’s own in the background?
Thanks
Hi, how to apply this code to the part of website that not provided by Woocommerce? Is it just by changing the $domain ???
So how to find my plugin $domain name?
You don’t have to know the $domain name – the code can examine every string and will only change the strings you want. I think that it is better to first check $domain so that the code can exit early if necessary.
Is the plugin on wordpress.org? If so someone can look at the code and show you where the $domain name is set for that plugin.
Hello,
I would like to transform “Username or email address” of my-account/form-login.php (woocommerce) to “E-Mail”. I added the following code to my childtheme’s functions.php but nothing changed – any idea what’s wrong?:
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case ‘Username or email address’ :
$translated_text = __( ‘Email address’, ‘royalchildtheme’ );
break;
}
return $translated_text;
}
add_filter( ‘gettext’, ‘my_text_strings’, 20, 3 );
The text is in a file that can be modified. Copy form-login.php into your theme directory e.g. to wp-content/theme_name/woocommerce/myaccount/form-login.php and change the text there.
This will be more efficient than using the gettext filter (which will be called for every page).
Hello Patrick,
I want to change text from woo-commerce order emails. So, I used your code snipet, but not worked for me. As I get default text email from woo-commerce.
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case ‘Your order has been received and is now being processed. Your order details are shown below for your reference:’ :
$translated_text = __( ‘The team from La Main Noire thanks you for your purchase, you\’ll be enjoying your new product very shortly.Your order has been received and is now being processed. Your order details are shown below for your reference:’, ‘woocommerce’ );
break;
}
return $translated_text;
}
add_filter( ‘gettext’, ‘my_text_strings’, 20, 3 );
Can you please help me?
To change this WooCommerce text you need to copy the wp-content/themes/woocommerce/emails/customer-processing-order.php file into wp-content/themes/YOUR_THEME/woocommerce/emails/customer-processing-order.php and change the file.
Hi Patrick, I just wanted to add my note of thanks. This awesome little filter still works perfectly in 2017. Best to you.
HI
Im trying to add some text to my related products roll over function … at the moment it reads ‘Details’ but i would like it to say ‘Click to view’
Is it possible to use css only or do i need to edit the php file? (still learning code)
I have added Toolset to change the layout of the single products page of wooCommerce
Any help would be greatly appreciated!
This is so simple and easy. Thanks for sharing this tip, Patrick!
Welcome! 🙂
In recent versions of WooCommerce, the string to replace has changed from “Related Products” to “Related products”.
NB lowercase P.
Anyone know why this won’t change the “Coupon:” label inside Cart Totals? Anyone ever successfully get that changed? That’s the one label that won’t change with gettext. Either that or I’m doing something wrong.
This is nice piece of code. Thanks for sharing.
this is in my related.php ( woocommerce Version 3.5.1)
and the above solution is not working for this version,
can you please tell me how to make this work.
Thanks
Many thanks for that, I used your solution and it worked great until I realize that the gettext hook was called million of times over 60 minutes (big traffic) so I looked at an alternative and this solution worked wonder for me: https://www.damiencarbery.com/2018/12/change-hardcoded-woocommerce-strings/