Waiting for author
Overview of the issue
When using WooCommerce Product Options by Barn2 with WPML, Product option strings appear as untranslated on cart, checkout, and mini-cart, even though they are correctly translated on the product page.
Workaround
Please, make sure of having a full site backup of your site before proceeding.
- In your theme’s functions.php file, paste the following code:
/** * Translate WooCommerce Product Options texts when adding to cart * using the plugin's own WPML integration. */ add_filter( 'woocommerce_add_cart_item_data', 'my_wpo_translate_cart_meta_with_wpml', 20, 4 ); function my_wpo_translate_cart_meta_with_wpml( $cart_item_data, $product_id, $variation_id, $quantity ) { // If there are no WPO options in this cart item, do nothing. if ( empty( $cart_item_data['wpo_options'] ) ) { return $cart_item_data; } // Make sure the plugin classes exist (plugin is active and loaded). if ( ! class_exists( 'Barn2PluginWC_Product_OptionsPlugin_Factory' ) || ! class_exists( 'Barn2PluginWC_Product_OptionsIntegrationWPML' ) || ! class_exists( 'Barn2PluginWC_Product_OptionsModelOption' ) ) { return $cart_item_data; } // Get the plugin instance and the WPML integration helper. $plugin = Barn2PluginWC_Product_OptionsPlugin_Factory::create( '', '' ); $wpml_integration = new Barn2PluginWC_Product_OptionsIntegrationWPML( $plugin ); foreach ( $cart_item_data['wpo_options'] as $option_id => &$option_data ) { // Load the option model so we can access the original data. $option = Barn2PluginWC_Product_OptionsModelOption::find( $option_data['option_id'] ?? 0 ); if ( ! $option ) { continue; } // 1) Translate the option name (the "key" shown in cart/checkout). $translated_name = $wpml_integration->translate_string( $option->name, $option, 'option_name' ); $option_data['name'] = $translated_name; // 2) Translate each choice label, if any. if ( empty( $option_data['choice_data'] ) || empty( $option->choices ) ) { continue; } // Build a map: choice_id => index, to reproduce the same index WPML uses. $index_by_id = []; foreach ( $option->choices as $idx => $choice ) { if ( isset( $choice['id'] ) ) { $index_by_id[ $choice['id'] ] = $idx; } } // Normalize the stored value to an array (covers both single and multi). $values = is_array( $option_data['value'] ) ? $option_data['value'] : [ $option_data['value'] ]; foreach ( $option_data['choice_data'] as $i => &$choice_data ) { if ( ! isset( $choice_data['label'] ) ) { continue; } // For free-text fields, there are usually no predefined choices to translate. if ( empty( $index_by_id ) ) { continue; } $value_for_this_choice = $values[ $i ] ?? null; if ( ! isset( $index_by_id[ $value_for_this_choice ] ) ) { continue; } $choice_index = $index_by_id[ $value_for_this_choice ]; $original_label = $option->choices[ $choice_index ]['label']; // Translate the choice label using the same context and index as when registered. $choice_data['label'] = $wpml_integration->translate_string( $original_label, $option, 'choice_label', $choice_index ); } } return $cart_item_data; } - Note: If you change language after having products in your cart, the labels will not be “translated”: they remain in the language that was active when the product was added (just like any other metadata that stores fixed texts). But it’s rare switching languages at that stage.
A permanent fix will soon be applied by Barn2, please remove the added workaround when it is deployed