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 |
---|---|---|---|---|---|---|
- | - | 9:00 – 18:00 | 9:00 – 18:00 | 9:00 – 18:00 | 9:00 – 18:00 | 9:00 – 18:00 |
- | - | - | - | - | - | - |
Supporter timezone: America/Lima (GMT-05:00)
This topic contains 18 replies, has 2 voices.
Last updated by Andreas W. 2 months, 3 weeks ago.
Assisted by: Andreas W..
Author | Posts |
---|---|
August 8, 2024 at 3:49 pm #16053680 | |
Marco |
Background of the issue: This is on WooCommerce, and WooCommerce Multilingual is used. Here's what we're doing: get_default_language(); // Force that language from now on $sitepress->switch_lang( $def_lang ); }); // Product insert/update -> Create translations (duplicates) if they do not exist add_action( 'woocommerce_rest_insert_product_object', function( $product, $request, $inserting ) { // Duplicate wpml_make_post_duplicates_action( $product->get_id() ); // Check: https://wpml.org/forums/topic/why-is-the-wpml_make_post_duplicates-hook-being-removed/ }, 10, 3 ); // Product variation insert/update -> Create translations (duplicates) if they do not exist add_action( 'woocommerce_rest_insert_product_variation_object', function( $product_variation, $request, $inserting ) { // Duplicate wpml_make_post_duplicates_action( $product_variation->get_id() ); // Check: https://wpml.org/forums/topic/why-is-the-wpml_make_post_duplicates-hook-being-removed/ // Try to set correct attributes on variation, without success - If we uncomment this it will work but we need to wp_die() // global $woocommerce_wpml; // $woocommerce_wpml->sync_variations_data->sync_product_variations_action( $product_variation->get_parent_id() ); // wp_die(); // If we uncomment this, it will work, as something else is running after and overwriting the attribute_pa_* variation product meta }, 10, 3 ); } Running wpml_make_post_duplicates_action after inserting the main product via the REST API works just fine. But when doing the same to variations, it works only partially and the attribute_pa_* variation product metas is just copied over and not set correctly with the translated attributes. For example, for a 'Color' attribute, and if English is the main language, when running the wpml_make_post_duplicates_action action, what will happen is this: Here's a visual example on a variation with two attributes in three languages. I suspect this is happening because on class-wcml-synchronize-product-data.php you're not adding the icl_make_duplicate action unless is_admin() or isCli() which is not true when using the REST API. But that might not be enough, as I tried to tweak the code there and it still didn't worked correctly. To try to fix this for us, we run $woocommerce_wpml->sync_variations_data->sync_product_variations_action( $product_variation->get_parent_id() ); after wpml_make_post_duplicates_action, which works and sets the correct values on attribute_pa_* but something else is running after because if we don't wp_die() the meta are overwritten again. Symptoms: Questions: |
August 8, 2024 at 9:47 pm #16054382 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
Hello, First of all, a duplicate will always share the same information as the original content. A duplicate in WPML is not a real translation. It is supposed to get overwritten anytime the original content is being saved. This means, that it would be expected that a duplicated product uses the same product details (here attributes) as the original product. Another problem with this approach is, that if you use custom attributes, that are created directly on the products, then you can only translate them with the WPML Translation Editor. This means, that if you open the translated product on the WordPress Editor, those fields are blocked and not editable. This is controlled by our addon WooCommerce Multilingual & Multi-Currency. The alternative might be to use global attributes, which are created at Products > Attributes. Those global attributes will be translatable at WooCommerce > WooCommerce Multilingual & Multi-Currency > Attributes. Best regards |
August 9, 2024 at 6:33 am #16054937 | |
Marco |
Hi Andreas, Thanks of your reply. We are aware duplicates are copies and not translations per se, but the goal here is that when the ERP creates products via the REST API, all the duplicates are created as placeholders, as the shop owner will then do one of two things: As I mentioned above, we have this working flawlessly on another customer, he just doesn't have variable products like this new one. Moving on, regarding attributes, we are using global attributes related at Products > Attributes already translated at WooCommerce > WooCommerce Multilingual & Multi-Currency > Attributes. The API is not creating attributes. We ensure those exist previously to create products and it's variations. Going back to the "A duplicate in WPML is not a real translation" issue, if I create a product manually on wp-admin, set its variations and then create duplicates via your Language metabox, the attributes show up as translated, even before I click the "translate independently" button, as you can see: hidden link If we do it via the REST API, the attributes are correct on the original product but the duplicates/translations show "any attribute" hidden link because the values are not correctly set on the database hidden link As you can see by our shared code, we currently are doing this: Another approach I just tried was to: So, in conclusion: even when the product is still a duplicate, the attributes are correctly set if the duplicate is created on the backend. Why is not possible to achieve the same via the REST API? Or, what is the preferred way of achieving it? |
August 9, 2024 at 6:44 pm #16057560 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
Thank you for the detailed answer! I will try to recreate this issue on a test site and then get back to you. In the meantime, can you please confirm if going to WooCommerce > WooCommerce Multilingual & Multi-Currency > Status > Troubleshooting and running the available options to sync variable products can solve this issue? |
August 9, 2024 at 7:16 pm #16057576 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
I created a test site and did the following: Login: hidden link 1) Create global product attributes and translate them 2) Create two variable products in the site's default language 3) Duplicate both products with Translation Management Result: 4) Product B was then sent to automatic translation Take note, that this workflow depends on, that on the original product the "WPML Translation Editor" is set as the translation method inside the right sidebar of the WordPress Editor. If the client wants to set the product to "Translate independently" and edit it inside the WordPress Editor, the translation method needs to be set to "WordPress Editor" first. --- It looks as if a third plugin might be causing the unexpected issues on your site. Did you already run a test in a minimal setup or do you maybe have a staging site ready on which I could investigate the issue? |
August 12, 2024 at 5:34 pm #16063438 | |
Marco |
Hi again Andreas, "I am using the WPML UI* in this case, as it should work similarly to your coded approach**. * I mentioned in my previous reply that I tested this and it worked just fine. The problem is when using code (wpml_make_post_duplicates_action()) to create the duplicates, as concluded on my last paragraph: "So, in conclusion: even when the product is still a duplicate, the attributes are correctly set if the duplicate is created on the backend*. Why is not possible to achieve the same via the REST API?** Or, what is the preferred way of achieving it?" * The WPML UI as you mentioned. Please re-read my reply from August 9, 2024 at 6:33 am and let me know if there's something not clear in my explanation. All tests were always performed only with WooCommerce and your plugins active and the used theme is Storefront. No other plugin or custom code is involved. |
August 13, 2024 at 6:31 pm #16067724 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
This would usually mean, that the issue is inside your custom function. Take kindly note that our support is usually not supposed to provide any custom code solutions. I have not tested this apporach yet, but could you please give this a try: // Ensure $sitepress is available $sitepress = isset($sitepress) ? $sitepress : null; if ($sitepress) { // Get the default language (ensure this function is defined and returns the expected language code) $def_lang = get_default_language(); // Force the language to default (make sure this is the correct way to set the language for your case) $sitepress->switch_lang($def_lang); } // Product insert/update -> Create translations (duplicates) if they do not exist add_action('woocommerce_rest_insert_product_object', function ($product, $request, $inserting) { // Ensure WPML function exists and is valid if (function_exists('wpml_make_post_duplicates_action')) { // Duplicate product wpml_make_post_duplicates_action($product->get_id()); } }, 10, 3); // Product variation insert/update -> Create translations (duplicates) if they do not exist add_action('woocommerce_rest_insert_product_variation_object', function ($product_variation, $request, $inserting) { // Ensure WPML function exists and is valid if (function_exists('wpml_make_post_duplicates_action')) { // Duplicate variation wpml_make_post_duplicates_action($product_variation->get_id()); } // Try to set correct attributes on variation if needed // Note: Ensure $woocommerce_wpml is available if uncommenting this code /* global $woocommerce_wpml; if (isset($woocommerce_wpml) && method_exists($woocommerce_wpml->sync_variations_data, 'sync_product_variations_action')) { $woocommerce_wpml->sync_variations_data->sync_product_variations_action($product_variation->get_parent_id()); } */ // If you face issues with attributes being overwritten, consider debugging why it's happening // Instead of wp_die(), use error logging or debugging tools to investigate }, 10, 3); If this will still not solve the issue, I further invite you to recreate the issue on the earlier provided test site and to provide me detailed steps about how to recreate the issue. |
August 14, 2024 at 8:47 am #16069359 | |
Marco |
Hi Andreas, I'm not asking for you to provide custom code solutions. I'm trying to use your available functions to replicate the "create duplicate" function on your plugin, but I'm thinking there might be a bug somewhere as it does not work as intended: again, the attributes are not correctly set, and I'm trying to help you fix this, so I and other users can use it. The solution you sent me is the same we're doing, but there's a function_exists('wpml_make_post_duplicates_action') check. I've done some more tests and I'm now convinced this is happening because on class-wcml-synchronize-product-data.php you're not adding the icl_make_duplicate action unless is_admin() or isCli(). I then changed "|| true" to " || wpml_is_rest_request()" and my code already works, with the small change that after creating each variation I need to call the wpml_make_post_duplicates_action() function on the MAIN product and not the newly created variation. So, can you please replace: if ( is_admin() || isCli() || wpml_is_rest_request() ) { by: if ( is_admin() || isCli() ) { On WooCommerce Multilingual, wcml-synchronize-product-data.php, function add_hooks() ? |
August 14, 2024 at 7:04 pm #16072274 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
I will give this a test and then get back to you. |
August 15, 2024 at 6:04 pm #16075713 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
I did some internal research and see that our developers actually provide the following documentation and workflow for this purpose: Did you five this a try already? |
August 15, 2024 at 9:18 pm #16076300 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
The issue here might be that, wpml_make_post_duplicates is usually reserved for Frontend calls: Please check the private message next after this comment. |
August 16, 2024 at 12:46 pm #16078304 | |
Marco |
Hi, If that hook/function is reserved for frontend calls, than the if ( is_admin() || isCli() ) { on WooCommerce Multilingual, wcml-synchronize-product-data.php, function add_hooks() makes no sense. I went to the provided test server and did this: I wasn't expecting this to work before making the proposed changes, but it did. After further investigation on my side, I realized what actually fixed it was to call wpml_make_post_duplicates_action with the main product ID and not with the variation ID, even when creating each variation via the REST API, so I guess the issue is solved. Still, it does make sense to change it to if ( is_admin() || isCli() || wpml_is_rest_request() ) { as REST can also be considered backend or authenticated at least, just like WP Admin and WP CLI. |
August 16, 2024 at 7:55 pm #16079246 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
I understand you right, that your implmentation is working as expected now, and the issue was realted to your code? About your request: You refer to this file? line 39: if ( is_admin() || isCli() ) { // filters to sync variable products. add_action( 'save_post', [ $this, 'synchronize_products' ], PHP_INT_MAX, 2 ); // After WPML. add_filter( 'icl_make_duplicate', [ $this, 'icl_make_duplicate' ], 110, 4 ); This logic will run if a post is saved or a duplicate is created. You would like to change this to: if ( is_admin() || isCli() || wpml_is_rest_request()) { // filters to sync variable products. add_action( 'save_post', [ $this, 'synchronize_products' ], PHP_INT_MAX, 2 ); // After WPML. add_filter( 'icl_make_duplicate', [ $this, 'icl_make_duplicate' ], 110, 4 ); Is this correct? I need to ask here, as such request will need to be explained in detail to the product manager: 1) With your approach, if a product is saved or duplicated when making a REST call, the variations will be synced. 2) If the third condition will be missing, no syncrhonization would occur, unless you implement a custom code solution. Did I understand this correctly? Now, could you please explain me how your REST request exactly looks, so that I get a better understanding about how such change can be a benefit for all users of WPML? I will need to run test before escalating such request and would like to ask you again to assist in recreating the issue on the provided test site. We need to make sure if this is not just a workaround for specific use cases and does not cause any issues or unepxected results if different workflows are applied. |
August 19, 2024 at 10:46 am #16083077 | |
Marco |
Actually it works now, even without that code changed, as mentioned in my last reply: <quote>I wasn't expecting this to work before making the proposed changes, but it did. After further investigation on my side, I realized what actually fixed it was to call wpml_make_post_duplicates_action with the main product ID and not with the variation ID, even when creating each variation via the REST API, so I guess the issue is solved.</quote> Anyway, still waiting for the real world testing to be 100% sure about that, so I would ask you to keep this open a few more days. I mentioned that it would make sense to add "|| wpml_is_rest_request()" as REST can also be considered backend or authenticated at least, just like WP Admin and WP CLI, but for my specific issue, it seems not to be needed after all (still, waiting for the real world testing). |
August 20, 2024 at 5:59 pm #16088036 | |
Andreas W. Supporter Languages: English (English ) German (Deutsch ) Timezone: America/Lima (GMT-05:00) |
Yes, thank you! The ticket will remain open for a maximum of 14 days and close automatically after this timeframe in case we do not receive any further message from you. Anyhow, you will be able to open a new ticket anytime and let the suport agent know that we handled a ticket for this issue earlier. About your request: "wpml_make_post_duplicates_action on a newly created product variation via REST" Please visit this test site: One-Click-Login: Take note that here I implemented the following hook to make sure that products are duplicated when published: add_action( 'wp_insert_post', 'my_duplicate_on_publish' ); function my_duplicate_on_publish( $post_id ) { // Avoid running on autosave if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // Avoid running on revisions if ( wp_is_post_revision( $post_id ) ) { return; } // Get the post object $post = get_post( $post_id ); // Ensure we are dealing with a product post type if ( ! $post || 'product' !== $post->post_type ) { return; } // Avoid recursion remove_action( 'wp_insert_post', 'my_duplicate_on_publish' ); // Check if the post is already duplicated or has translations $is_translated = apply_filters( 'wpml_element_has_translations', '', $post_id, $post->post_type ); // Make duplicates if the product does not already have translations if ( !$is_translated ) { do_action( 'wpml_admin_make_post_duplicates', $post_id ); } // Re-hook the action add_action( 'wp_insert_post', 'my_duplicate_on_publish' ); } Hook: https://wpml.org/wpml-hook/wpml_admin_make_post_duplicates/ This is a dedicated hook for admin calls and it should also fire when for example making a REST API request with Postman. Once a new product is created, this hook will create a duplicate including variations. Further, the duplicate will get overwritten automatically each time the original content is updated. Do i understand right, that this what you are trying to achieve? Could you please give this a test? |
The topic ‘[Closed] Running wpml_make_post_duplicates_action on a newly created product variation via REST does not work…’ is closed to new replies.