Change Text Strings On Specific WooCommerce Endpoints - php

I'm trying to conditionally change strings on WooCommerce My Account Endpoints. Each time I try to add an endpoint condition it either breaks the site or doesn't work; however when I don't use the condition the string replace works. Maybe someone can point out where I'm going wrong.
Working Snippet - Without Condition
function change_endpoint_text( $translated ) {
$translated = str_ireplace( 'List of coupons which are valid & available for use. Click on the coupon to use it. The coupon discount will be visible only when at least one product is present in the cart.', 'List of vouchers which are valid & available for use. Click on a voucher to use it. The discount will be visible only when at least one product is present in the cart.', $translated );
return $translated;
}
add_filter( 'gettext', 'change_endpoint_text' );
Conditional Snippet Test - Not Working
Note: I also tried using an is_account_page condition that seemed to break the site.
function change_endpoint_text( $translated ) {
if( is_wc_endpoint_url('wc-smart-coupons') ) {
$translated = str_ireplace( 'List of coupons which are valid & available for use. Click on the coupon to use it. The coupon discount will be visible only when at least one product is present in the cart.', 'List of vouchers which are valid & available for use. Click on a voucher to use it. The discount will be visible only when at least one product is present in the cart.', $translated );
}
return $translated;
}
add_filter( 'gettext', 'change_endpoint_text' );
Any help would be appreciated.

You can also check for end points using $wp->query_vars['custom_endpoint'].
For example,
function change_endpoint_text ( $translated_text, $text, $domain ) {
global $wp;
if ( isset( $wp->query_vars['wc-smart-coupons'] ) ) {
if ($translated_text == 'some existing text') {
$translated_text = __( 'The new replaced text', 'woocommerce');
}
}
return $translated_text;
}
add_filter( 'gettext', 'change_endpoint_text' );

Related

Translate Woocommerce Add to cart button & Cart widget

I have a problem with translating the Add to cart button on woocommerce.
My website is: http://test.mk/OPA
The website is in albanian and english. First language is English.
I have installed Polylang Pro plugin and also tried with Loco translate.
I have changed the "name" of the Add to cart button with this code in functions.php:
//To change add to cart text on single product page
add_filter( 'woocommerce_product_single_add_to_cart_text', 'woocommerce_custom_single_add_to_cart_text' );
function woocommerce_custom_single_add_to_cart_text() {
return __( 'Order Now', 'woocommerce' );
}
// To change add to cart text on product archives(Collection) page
add_filter( 'woocommerce_product_add_to_cart_text', 'woocommerce_custom_product_add_to_cart_text' );
function woocommerce_custom_product_add_to_cart_text() {
return __( 'Order Now', 'woocommerce' );
}
So, what I really need to translate is Order Now.
I added the string using this code:
add_action('init', function() {
pll_register_string('woocommerce_product_add_to_cart_text', 'Order Now', 'WooCommerce');
});
It is in strings in the polylang plugin, but it is not translating.
Does someone know how to help me to translate the button & the Cart wiget that is also in the website?
Thank you in advance.
You can try with this function:
// change the text of the add to cart button according to the language
add_filter( 'woocommerce_product_add_to_cart_text', 'woocommerce_custom_single_add_to_cart_text', 99, 1 );
add_filter( 'woocommerce_product_single_add_to_cart_text', 'woocommerce_custom_single_add_to_cart_text', 99, 1 );
function woocommerce_custom_single_add_to_cart_text( $text ) {
// returns the current language "Polylang"
switch ( pll_current_language() ) {
case 'en':
return __( 'Order Now', 'woocommerce' );
case 'sq':
return __( 'Porosit tani', 'woocommerce' );
}
return $text;
}
Change the text of the "Add to cart" button according to the current language of the site.
This function should work but I believe you should search the Polylang plugin documentation to correctly translate the string.
The code must be inserted in the functions.php file of the active theme.

Change "No shipping method has been selected.…" from WooCommerce checkout notice

I am trying to tackle an issue by renaming the default message below when there are no shipping methods available, either set by rule based plugins or there simply isn't any methods set in WooCommerce.
No shipping method has been selected. Please double check your address, or contact us if you need any help.
I have used the below function using the snippets plugin and I can confirm it changes the message in the cart and checkout underneath the shipping label.
However, if someone then attempts to checkout they get a red WooCommerce error message at the top of the screen which is still the default message above.
How do I also change this error message ? I would like to change it to something different than what my code below shows to give me the flexibility to put a short message in the cart totals box and a longer more informational message as to why no methods are available.
My Function:
add_filter( 'woocommerce_cart_no_shipping_available_html', 'no_shipping_available_html' );
add_filter( 'woocommerce_no_shipping_available_html', 'no_shipping_available_html' );
function no_shipping_available_html( $message ) {
$country = WC()->customer->get_shipping_country();
if ( !empty( $country ) ) {
$all_countries = WC()->countries->get_countries();
return sprintf( 'Orders delivered into the EU are limited to €150 (inc shipping) or a max weight of 2kg. The items in you cart exceed this limit. Please remove an item or reduce the quantity required to bring the order value/weight within the permitted values.', $all_countries[ $country ] );
}
return 'Orders delivered into the EU are limited to €150 (inc shipping) or a max weight of 2kg. The items in you cart exceed this limit. Please remove an item or reduce the quantity required to bring the order value/weight within the permitted values.';
}
This text is located in WC_Checkout Class inside validate_checkout() method. There are no filters to make changes to it, but you can use WordPress gettext filter for that as follows:
add_filter( 'gettext', 'change_checkout_no_shipping_method_text', 10, 3 );
function change_checkout_no_shipping_method_text( $translated_text, $text, $domain ) {
if ( is_checkout() && ! is_wc_endpoint_url() ) {
$original_text = 'No shipping method has been selected. Please double check your address, or contact us if you need any help.';
$new_text = 'Here your own text replacement.';
if ( $text === $original_text ) {
$translated_text = $new_text;
}
}
return $translated_text;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
You could use a plugin like Loco translate if you want, that makes easier to do your job.. but you could try this code, similar to #LoicTheAztec inside functions.php (either on your theme or child theme file)
add_filter( 'gettext', 'ds_translate_woocommerce_strings', 999, 3 );
function ds_translate_woocommerce_strings( $translated,
$untranslated, $domain ) {
if ( ! is_admin() ) {
switch ($translated) {
case 'the message you want to be translated exactly as you see it in WP':
$translated = 'your new message';
break;
}
}
return $translated;
}

Customize Cart Totals and Checkout Totals Text based on product categories

I'd like to customize the text in Cart and Checkout order summary tables based on the product category (or some other logic). For example, for the 'Total' text (see image) - if the cart contains products in a category called "Groceries", then I'd like for text in the order summary to be displayed as 'Totals Estimate' text (see image below). If the cart does not contain any grocery items, then I want the default text.
I found a solution that got me started, but need some more help.
Per this link, I copied over files from woocommerce/templates/ into my child theme and named it woocommerce/. From review_order.php file, I need to edit the section below for example.
<th><?php _e( 'Total', 'woocommerce' ); ?></th>
However, I can't just replace that with a hard-coded string as my text depends on logic. So, I need to replace the string with a function.
I want to instead do something like this below:
<th><?php _e( get_my_custom_text(), 'woocommerce' ); ?></th>
, where get_my_custom_text() returns the appropriate text based on some logic e.g. categories of items in the cart.
Where would I need to place the file containing function get_my_custom_text() so that the review_order.php can see the function?
Is this the best way to achieve what I'm trying to do?
Update:
Following discussions below, I'm adding my get_custom_text() code. I've attempted to solve this two ways: first is the woocommerce files way and second one is the suggestion below to use the add_filter( 'gettext', 'my_text_strings', 20, 3 ) hook. In both cases, get_my_custom_text() doesn't seem to work when inspecting the cart. See code below using the hook method. I've gotten an error on the get_cart_contents_count(), and also got the white screen of death
[23-Mar-2019 11:14:13 UTC] PHP Fatal error: Uncaught Error: Call to a member function get_cart_contents_count() on null in /opt/wordpress/htdocs/wp-content/themes/divi-child/functions.php:446
Also got:
[23-Mar-2019 11:16:05 UTC] PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 20480 bytes) in /opt/wordpress/htdocs/wp-includes/class-wp-hook.php on line 279
add_filter( 'gettext', 'my_text_strings', 20, 3 );
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Total' :
$translated_text = __( get_my_custom_text(), 'woocommerce' );
break;
}
return $translated_text;
}
function get_my_custom_text()
{
$is_groceries = has_groceries();
if($is_groceries){
return 'Total Estimate';
}else{
return 'Total';
}
}
//checks whether cart has any items in the "groceries" category
function has_groceries()
{
if( !$cart = WC()->cart ){
return false;
}
//not sure how error gets here if cart is null
write_log('cart contents: '. WC()->cart->get_cart_contents_count());
$categories = array(
'181' => 'groceries'
);
foreach( $cart->get_cart() as $cart_item ){
foreach ($categories as $category => $value) {
if( has_term( $category, 'product_cat', $cart_item['product_id']) ){
return true;
}
}
}
return false;
}
Why are you trying to get in the Log, the cart items count (in your function). This is not really useful.
I have simplified and revisited your code and I dont use get_my_custom_text() in the last function as using has_groceries() instead is simpler and effective:
// Custom function based on has_groceries() conditional function that returns a string
function get_my_custom_text() {
return has_groceries() ? 'Total Estimate' : 'Total';
}
// Custom conditional function checking for a specific product category in cart items
function has_groceries() {
if( ! WC()->cart->is_empty() ){
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ){
if( has_term( array('groceries'), 'product_cat', $cart_item['product_id']) )
return true;
}
}
return false;
}
// Change 'Total' text conditionally
add_filter( 'gettext', 'changing_total_text_string', 10, 3 );
function changing_total_text_string( $translated_text, $text, $domain ) {
// Only in cart and checkout pages
if ( ( ( is_checkout() && ! is_wc_endpoint_url() ) || is_cart() )
&& $text === 'Total' && $domain === 'woocommerce' && has_groceries() ) {
$translated_text = __('Total Estimate');
}
return $translated_text;
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
This way it will avoid an endless loop on "Total" text replacement.
That method is fine, and you would add the function to your functions.php in your child theme.
However, the method below is likely better, as you don't need to modify woocommerce at all! You'll still need your same function, but everything can reside in functions.php now. This uses Wordpress's gettext filter.
add_filter( 'gettext', 'my_text_strings', 20, 3 );
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Total' :
$translated_text = __( get_my_custom_text(), 'woocommerce' );
break;
}
return $translated_text;
}

Change add to cart stock error notice in WooCommerce

When a customer tries to add too many of an item to cart, they see this error notice:
You cannot add that amount to the cart - we have X in stock and you already have Y in your cart.
This behavior is included on WC_Cart add_to_cart() method source code at line 1067.
I will like to hide stock details and replace it with:
You cannot add that amount to the cart — we don't have enough in stock.
How to change this add to cart stock error notice in WooCommerce, without overwriting source code?
That is possible using gettext filter hook in a custom hooked function this way:
add_filter( 'gettext', 'custom_add_to_cart_stock_error_notice', 10, 3 );
function custom_add_to_cart_stock_error_notice( $translated, $text, $domain ) {
if ( $text === 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.' && 'woocommerce' === $domain ) {
$translated = __("You cannot add that amount to the cart — we don't have enough in stock.", $domain );
}
return $translated;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
You can change the said text without modifying the plugin files with the help of "Say What" Plugin. Follow the following steps to change the text:
Install Say What plugin
Visit Tools > Text Changes
Click Add New
Fill the fields as per your need e.g.
Original string: You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.
Text domain: woocommerce
Text context:
Replacement string: You cannot add that amount to the cart — we don't have enough in stock.
Click Add button to save the changes.
Note that #loictheaztec's code works except that the quotes need to be changed to single quote marks in the fourth line if you want to use quantities
add_filter( 'gettext', 'custom_add_to_cart_stock_error_notice', 10, 3 );
function custom_add_to_cart_stock_error_notice( $translated, $text, $domain ) {
if ( $text === 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.' && 'woocommerce' === $domain ) {
$translated = __('You cannot add that to the cart — we have %1$s in stock and you already have %2$s in your cart.', $domain );
}

WooCommerce - Remove variation from product title in order details and email

I have a variation called "China" on some of my products. The way WooCommerce works, is that inside the cart, order details and emails, the variations are being appended to the product title. I would like to have the word "China" removed from the title in the cart, checkout, order details and email.
Current Title: "Apple MacBook Pro 15 - China, 16GB Ram, 512GB SSD"
Required Title: "Apple MacBook Pro 15 - 16GB Ram, 512GB SSD"
I managed to remove it from the title when it's inside the cart and checkout page, using this code:
function remove_variation_from_product_title( $title, $cart_item, $cart_item_key ) {
$_product = $cart_item['data'];
if ( $_product->is_type( 'variation' ) ) {
$replace = array( 'China,', 'China' );
$title = str_replace( $replace, '', $title);
return apply_filters( 'woocommerce_product_variation_title', $title );
}
return $title;
}
add_filter( 'woocommerce_cart_item_name', 'remove_variation_from_product_title', 10, 3 );
But as you can see from the filter, it only removes it from the cart. Once the order is made, the full title with variations are being shown again in the order details page as well as in the email that is sent from the customer.
I did come across another filter called woocommerce_order_items_meta_display, but failed to get anywhere with it.
Does anyone know how I could filter the product title across the entire store, and not just in the cart and checkout page?
Thanks.
Update:
Found the solution. woocommerce_order_item_name did the trick. It also applies it to the email that is sent to the customer.
function remove_variation_from_product_title_order( $title, $item, $is_visible ) {
$_product = $item['data'];
$replace = array( 'China,', 'China' );
$title = str_replace( $replace, '', $title);
return apply_filters( 'woocommerce_product_variation_title', $title );
}
add_filter( 'woocommerce_order_item_name', 'remove_variation_from_product_title_order', 10, 3 );
Found it. woocommerce_order_item_name did the trick. It also applies it to the email that is sent to the customer.
function remove_variation_from_product_title_order( $title, $item, $is_visible ) {
$_product = $item['data'];
$replace = array( 'China,', 'China' );
$title = str_replace( $replace, '', $title);
return apply_filters( 'woocommerce_product_variation_title', $title );
}
add_filter( 'woocommerce_order_item_name', 'remove_variation_from_product_title_order', 10, 3 );
I'm working on a similar problem and stumbled upon woocommerce_order_item_name as well. In my case, the WooCommerce order notification emails are displaying the product title with variant (much like your example) but also re-listing the attribute name (used to create the variations - in this case "Submission Type") along with the product title with variant below for each product, like so:
Online Application - Full Application
Submission Type: Full Application
Does anyone know how exactly the output is created for this and if applying a filter to woocommerce_order_item_name can modify the output so that the the second line specifying the variation is removed?
I struggled to find out what exactly can be passed to woocommerce_order_item_name as arguments and how the variation name is being output. How did you find this?
Right now I have a start and seem to be able to add a condition for the matching products I want to modify based on the main product title and separator prefix used at the start of the product, but not sure how to find/alter the variation appearing on the second line in the emails:
add_filter( 'woocommerce_order_item_name', 'edit_order_item_name');
function edit_order_item_name($item) {
$prefix = 'Online Application - ';
if (substr($item, 0, strlen($prefix)) == $prefix) {
// do something here to remove the variation type and name from appearing below the product name
}
else {
return $item;
}
}

Categories