This is the technical support forum for WPML - the multilingual WordPress plugin.
Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
| 10:00 – 14:00 | 10:00 – 14:00 | 10:00 – 14:00 | 10:00 – 14:00 | 10:00 – 14:00 | - | - |
| 16:00 – 20:00 | 16:00 – 20:00 | 16:00 – 20:00 | 16:00 – 20:00 | 16:00 – 20:00 | - | - |
Supporter timezone: Asia/Jerusalem (GMT+02:00)
Tagged: Compatibility
This topic contains 1 replies, has 0 voices.
Last updated by Itamar 2 weeks, 6 days ago.
Assisted by: Itamar.
| Author | Posts |
|---|---|
| February 11, 2026 at 7:26 pm #17814164 | |
|
matthiasG-45 |
Bug: WCML's resync_bundle() in class-wcml-product-bundles.php fails to update bundled_by references in child cart items when the parent bundle's cart key changes during session reload on secondary languages. This lets the bundle child items in the cart, the bunde item remains, the customer can't check out. PS: I added a temporary fix to our WP installation, I overwrote your resync_bundle Now customers can check out in English AND German without a problem. This is my fix in case you want to know it:
/**
* Fix WCML Product Bundles cart key mismatch bug.
* WCML's resync_bundle() fails to update child bundled_by references
* when the parent's cart key changes due to language translation.
* This replacement adds a fallback parent lookup.
*/
// Unhook WCML's broken resync_bundle and replace with fixed version.
add_action( 'init', function() {
// Get WCML Product Bundles instance.
global $woocommerce_wpml;
if ( ! $woocommerce_wpml || ! isset( $woocommerce_wpml->compatibility ) ) return;
// Find and remove WCML's resync_bundle hook.
global $wp_filter;
if ( isset( $wp_filter['woocommerce_get_cart_item_from_session'] ) ) {
foreach ( $wp_filter['woocommerce_get_cart_item_from_session']->callbacks as $priority => $callbacks ) {
foreach ( $callbacks as $id => $callback ) {
if ( is_array( $callback['function'] )
&& is_object( $callback['function'][0] )
&& $callback['function'][0] instanceof WCML_Product_Bundles
&& $callback['function'][1] === 'resync_bundle' ) {
remove_filter( 'woocommerce_get_cart_item_from_session', $callback['function'], $priority );
}
}
}
}
// Also remove WCML's resync_bundle_clean.
if ( isset( $wp_filter['woocommerce_cart_loaded_from_session'] ) ) {
foreach ( $wp_filter['woocommerce_cart_loaded_from_session']->callbacks as $priority => $callbacks ) {
foreach ( $callbacks as $id => $callback ) {
if ( is_array( $callback['function'] )
&& is_object( $callback['function'][0] )
&& $callback['function'][0] instanceof WCML_Product_Bundles
&& $callback['function'][1] === 'resync_bundle_clean' ) {
remove_filter( 'woocommerce_cart_loaded_from_session', $callback['function'], $priority );
}
}
}
}
}, 20 );
// Our fixed resync_bundle replacement (same priority 5 as WCML original).
add_filter( 'woocommerce_get_cart_item_from_session', function( $cart_item, $session_values, $cart_item_key ) {
// PART 1: Handle parent bundle items (same as WCML original).
if ( isset( $cart_item['bundled_items'] ) && $cart_item['data'] instanceof WC_Product && $cart_item['data']->get_type() === 'bundle' ) {
$current_bundle_id = apply_filters( 'wpml_object_id', $cart_item['product_id'], 'product', true );
if ( $cart_item['product_id'] != $current_bundle_id ) {
if ( isset( $cart_item['data']->bundle_data ) && is_array( $cart_item['data']->bundle_data ) ) {
$old_bundled_item_ids = array_keys( $cart_item['data']->bundle_data );
$cart_item['data'] = wc_get_product( $current_bundle_id );
if ( isset( $cart_item['data']->bundle_data ) && is_array( $cart_item['data']->bundle_data ) ) {
$new_bundled_item_ids = array_keys( $cart_item['data']->bundle_data );
$remapped_bundled_item_ids = [];
foreach ( $old_bundled_item_ids as $idx => $old_id ) {
$remapped_bundled_item_ids[ $old_id ] = $new_bundled_item_ids[ $idx ];
}
$cart_item['remapped_bundled_item_ids'] = $remapped_bundled_item_ids;
if ( isset( $cart_item['stamp'] ) ) {
$new_stamp = [];
foreach ( $cart_item['stamp'] as $bid => $stamp_data ) {
$new_stamp[ $remapped_bundled_item_ids[ $bid ] ] = $stamp_data;
}
$cart_item['stamp'] = $new_stamp;
}
}
}
}
}
// PART 2: Handle child bundled items - THIS IS THE FIX.
if ( isset( $cart_item['bundled_by'] ) ) {
$parent_key = $cart_item['bundled_by'];
$parent_item = null;
// Try original key first.
if ( isset( WC()->cart->cart_contents[ $parent_key ] ) ) {
$parent_item = WC()->cart->cart_contents[ $parent_key ];
} else {
// FALLBACK: Parent key changed - find parent by searching cart contents.
foreach ( WC()->cart->cart_contents as $key => $item ) {
if ( ! empty( $item['bundled_items'] ) && ! empty( $item['remapped_bundled_item_ids'] ) ) {
// Found a bundle parent with remapped IDs - this is our parent.
$parent_item = $item;
$parent_key = $key;
$cart_item['bundled_by'] = $key;
break;
}
}
}
// Apply remapped IDs if parent found.
if ( $parent_item &&
isset( $parent_item['remapped_bundled_item_ids'] ) &&
isset( $cart_item['bundled_item_id'] ) &&
isset( $parent_item['remapped_bundled_item_ids'][ $cart_item['bundled_item_id'] ] ) ) {
$remapped = $parent_item['remapped_bundled_item_ids'];
$cart_item['bundled_item_id'] = $remapped[ $cart_item['bundled_item_id'] ];
if ( isset( $cart_item['stamp'] ) ) {
$new_stamp = [];
foreach ( $cart_item['stamp'] as $bid => $stamp_data ) {
if ( isset( $remapped[ $bid ] ) ) {
$new_stamp[ $remapped[ $bid ] ] = $stamp_data;
} else {
$new_stamp[ $bid ] = $stamp_data;
}
}
$cart_item['stamp'] = $new_stamp;
}
}
}
return $cart_item;
}, 5, 3 );
// Clean up remapped IDs after session load (same as WCML original).
add_action( 'woocommerce_cart_loaded_from_session', function( $cart ) {
if ( empty( $cart->cart_contents ) ) return;
// STEP 1: Final fix for any remaining orphaned children.
$parent_map = [];
foreach ( $cart->cart_contents as $key => $item ) {
if ( ! empty( $item['bundled_items'] ) ) {
$parent_map[ intval( $item['product_id'] ) ] = $key;
}
}
if ( ! empty( $parent_map ) ) {
global $wpdb;
$table = $wpdb->prefix . 'woocommerce_bundled_items';
foreach ( $cart->cart_contents as $key => $item ) {
if ( empty( $item['bundled_by'] ) ) continue;
if ( isset( $cart->cart_contents[ $item['bundled_by'] ] ) ) continue;
$bundled_item_id = isset( $item['bundled_item_id'] ) ? intval( $item['bundled_item_id'] ) : 0;
if ( ! $bundled_item_id ) continue;
$bundle_id = $wpdb->get_var( $wpdb->prepare(
"SELECT bundle_id FROM {$table} WHERE bundled_item_id = %d", $bundled_item_id
) );
if ( $bundle_id && isset( $parent_map[ intval( $bundle_id ) ] ) ) {
WC()->cart->cart_contents[ $key ]['bundled_by'] = $parent_map[ intval( $bundle_id ) ];
}
}
// Rebuild bundled_items arrays.
foreach ( $parent_map as $pid => $pkey ) {
$children = [];
foreach ( WC()->cart->cart_contents as $k => $i ) {
if ( ! empty( $i['bundled_by'] ) && $i['bundled_by'] === $pkey ) {
$children[] = $k;
}
}
WC()->cart->cart_contents[ $pkey ]['bundled_items'] = $children;
}
}
// STEP 2: Clean up remapped IDs.
foreach ( $cart->cart_contents as $cart_item_key => $cart_item ) {
if ( isset( $cart_item['bundled_items'] ) && isset( $cart_item['remapped_bundled_item_ids'] ) ) {
unset( WC()->cart->cart_contents[ $cart_item_key ]['remapped_bundled_item_ids'] );
}
}
}, 0 );
|
| February 12, 2026 at 7:10 pm #17818523 | |
|
Itamar WPML Supporter since 02/2016
Languages: English (English ) Timezone: Asia/Jerusalem (GMT+02:00) |
Hi, I've tried to replicate the issue you described on a fresh WordPress installation with WooCommerce, Product Bundles for WooCommerce, and WPML, but I was unable to replicate it. Here is what I tried according to your description of the problem. 1. I translated three products from English into German. 2. I edited the T-shirt product and made it a bundled product together with the Cap and Sunglasses products. 3. I switched to German and added the translated German T-shirt product to the cart. 4. I clicked to view the cart and got the bundled product as expected. Please see the attached screenshot bundle-in-cart-ok.jpg. It is as I get it if I add it to the cart in English. I see no problem here. In addition, I also want to point out something important to you. When using a plugin like Product Bundles for WooCommerce, we recommend switching to the 'Prompt for a confirmation and reset the cart' option in WooCommerce -> WCML -> Settings -> Cart -> Switching languages/currencies, when there are items in the cart. This is because keeping the 'Synchronize cart content when switching languages/currencies' option enabled can cause problems, as you describe, when using a plugin like Product Bundles for WooCommerce. We even provide a warning about this in the admin. Please see the attached screenshot bundle-admin-message.jpg. Therefore, if your case involves switching the cart when it contains bundled products, please use the options mentioned above. Please note that my weekends are Friday to Saturday. If you need further assistance, I'll be available to continue checking this issue and helping you next week. Regards, |
The topic ‘[Closed] Woocommerce bundle items disappear during checkout in 2nd language’ is closed to new replies.

