Forum Replies Created

Viewing 15 replies - 1 through 15 (of 42 total)
  • Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hello,

    Yes, this is the plugin I use:

    https://github.com/qtranslate/qtranslate-xt

    I also already have the LiteSpeed language cookie vary rule in .htaccess:

    # BEGIN LITESPEED LANGUAGE COOKIE VARY
    <IfModule LiteSpeed>
    RewriteEngine On
    RewriteRule .? - [E=Cache-Vary:qtrans_front_language]
    </IfModule>
    # END LITESPEED LANGUAGE COOKIE VARY
    

    It works correctly for Page Cache, but it does not seem to affect Object Cache / Memcached.

    So yes, I think the missing part is exactly what you mentioned: Object Cache also needs to vary by the selected language.

    Could you please advise how to add this vary for Object Cache specifically?

    Thank you.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Here’s the fix itself for the term names:

    if ( ! function_exists( 'mh_qtx_force_current_language_term_name' ) ) {
    
        function mh_qtx_get_current_qtranslate_language() {
            global $q_config;
    
            if ( isset( $q_config['language'] ) && is_string( $q_config['language'] ) && $q_config['language'] !== '' ) {
                return $q_config['language'];
            }
    
            return '';
        }
    
        function mh_qtx_get_translated_term_name_from_i18n_config( $term, $lang ) {
            if ( ! is_object( $term ) || ! $lang ) {
                return null;
            }
    
            if ( ! isset( $term->i18n_config ) ) {
                return null;
            }
    
            $config = $term->i18n_config;
    
            if ( is_object( $config ) ) {
                $config = json_decode(
                    wp_json_encode( $config, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR ),
                    true
                );
            }
    
            if ( ! is_array( $config ) ) {
                return null;
            }
    
            // Structure
            if (
                isset( $config['name']['ts'][ $lang ] ) &&
                is_string( $config['name']['ts'][ $lang ] ) &&
                $config['name']['ts'][ $lang ] !== ''
            ) {
                return $config['name']['ts'][ $lang ];
            }
    
            // Fallback variants for other possible qTranslate-XT structures.
            if (
                isset( $config['ts'][ $lang ] ) &&
                is_string( $config['ts'][ $lang ] ) &&
                $config['ts'][ $lang ] !== ''
            ) {
                return $config['ts'][ $lang ];
            }
    
            if (
                isset( $config['name'][ $lang ] ) &&
                is_string( $config['name'][ $lang ] ) &&
                $config['name'][ $lang ] !== ''
            ) {
                return $config['name'][ $lang ];
            }
    
            return null;
        }
    
        function mh_qtx_force_current_language_term_name( $term ) {
            if ( ! $term instanceof WP_Term ) {
                return $term;
            }
    
            $lang = mh_qtx_get_current_qtranslate_language();
    
            if ( ! $lang ) {
                return $term;
            }
    
            $translated_name = mh_qtx_get_translated_term_name_from_i18n_config( $term, $lang );
    
            if ( null === $translated_name ) {
                return $term;
            }
    
            /*
             * Clone the term to avoid mutating a shared cached object reference directly.
             */
            $term = clone $term;
            $term->name = $translated_name;
    
            return $term;
        }
    
        function mh_qtx_force_current_language_terms_list( $terms ) {
            if ( is_wp_error( $terms ) || empty( $terms ) ) {
                return $terms;
            }
    
            if ( ! is_array( $terms ) ) {
                return $terms;
            }
    
            foreach ( $terms as $index => $term ) {
                if ( $term instanceof WP_Term ) {
                    $terms[ $index ] = mh_qtx_force_current_language_term_name( $term );
                }
            }
    
            return $terms;
        }
    
        /*
         * Core term filters.
         */
        add_filter( 'get_term', function( $term ) {
            return mh_qtx_force_current_language_term_name( $term );
        }, 9999 );
    
        add_filter( 'get_terms', function( $terms ) {
            return mh_qtx_force_current_language_terms_list( $terms );
        }, 9999 );
    
        add_filter( 'get_the_terms', function( $terms ) {
            return mh_qtx_force_current_language_terms_list( $terms );
        }, 9999 );
    
        /*
         * WooCommerce-specific safety layer.
         *
         * This catches terms returned through wc_get_product_terms().
         */
        add_filter( 'woocommerce_get_product_terms', function( $terms ) {
            return mh_qtx_force_current_language_terms_list( $terms );
        }, 9999 );
    
        /*
         * WooCommerce attribute output safety layer.
         *
         * This catches $product->get_attribute( 'pa_xxx' ) output.
         */
        add_filter( 'woocommerce_product_get_attributes', function( $attributes ) {
            return $attributes;
        }, 9999 );
    
        add_filter( 'woocommerce_product_get_default_attributes', function( $attributes ) {
            return $attributes;
        }, 9999 );
    }
    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hello,

    Thank you for your reply.

    I did some additional testing and found one important detail.

    Excluding the woocommerce-attributes group from LiteSpeed Object Cache fixed the issue with translated WooCommerce attribute labels. However, it did not fix the translated attribute values.

    The remaining issue seems to be related to cached WP_Term objects. In my case, taxonomy term names used as WooCommerce attribute values can remain cached in the first visited language. Then, when the frontend language changes, WooCommerce receives the same cached WP_Term->name, so the attribute value is still displayed in the wrong language.

    As a temporary compatibility fix, I added a filter that checks the current qTranslate-XT language and replaces WP_Term->name from the term’s i18n_config, where qTranslate-XT already stores translations for all languages.

    This temporary fix solves the attribute value translation issue on my site, but I do not think this is the best long-term solution because it works around the cached object after it has already been returned.

    So the current situation is:

    • Excluding woocommerce-attributes from Object Cache fixes WooCommerce attribute labels.
    • Attribute values are still affected because cached WP_Term objects can contain the term name rendered/stored for another language.
    • A PHP workaround using get_term, get_terms, get_the_terms, and woocommerce_get_product_terms can force the correct translated term name.
    • The issue appears only with LiteSpeed Object Cache + Memcached enabled.
    • With LiteSpeed Object Cache disabled, qTranslate-XT and WooCommerce attribute values work correctly.

    Because of this, I think the most useful improvement would be one of the following:

    1. A way to exclude specific object cache groups related to terms/taxonomies more clearly.
    2. A debug/logging option to show which group and key is used for a cached term/transient.
    3. A PHP filter to vary object cache keys by language, for example using the qtrans_front_language cookie or current qTranslate-XT language.
    4. A PHP filter to prevent selected transients or term-related objects from being stored in persistent Object Cache.

    For multilingual WooCommerce sites, the main problem is that some cached objects are not language-neutral. If a cached object contains already-translated data, then the object cache key probably needs language context, or developers need a safe way to exclude/vary these entries.

    Please let me know if there is already a recommended LiteSpeed-compatible way to exclude cached WooCommerce term objects / taxonomy terms, or to vary object cache entries by language.

    Thank you.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Done, thanks, I will mark this topic as resolved.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Зачем вы помечаете тему как “решенную” – если вы уже как год ничего не решаете. Вы продолжаете в техподдержке писать один и тот же ответ, оправдывая свое безделие. Очень разочарован покупкой и столь отстающей от современности поддержкой плагинов.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    I’m marking this topic as resolved, since its the problem of the qTranslate-XT plugin.

    If someone’s need a fix – just comment assert() function on the line 102 in qtranslate_core.php. This check doesn’t need in production only for debugging.

    PS: The problem was existed in PHP 7.4 too, but everything was worked just because PHP 7.4 and lower versions throws warning message in case of failure, and PHP8+ throws exception. Explanation of how assert() function work in PHP8+ https://php.watch/versions/8.0/assert-throws

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hey Mikhail, this is what I get in log:

    2023-02-08T08:26:50+00:00 CRITICAL Uncaught AssertionError: detected in parse_language_info - cancelled by can_redirect, url_info={
    "cookie_lang_front": "ru",
    "cookie_front_or_admin_found": true,
    "scheme": "https",
    "host": "antik.ua",
    "path": "\/",
    "query": "wc-ajax=aws_action",
    "path-base": "",
    "doing_front_end": true,
    "wp-path": "\/",
    "language": "ru",
    "doredirect": "detected in parse_language_info - cancelled by can_redirect",
    "set_cookie": true
    } in /home/antikua/antik.ua/www/wp-content/plugins/qtranslate-xt/qtranslate_core.php:102
    Stack trace:
    
    0 /home/antikua/antik.ua/www/wp-content/plugins/qtranslate-xt/qtranslate_core.php(102): assert(false, 'detected in par…')
    
    1 /home/antikua/antik.ua/www/wp-includes/class-wp-hook.php(308): qtranxf_init_language('')
    
    2 /home/antikua/antik.ua/www/wp-includes/class-wp-hook.php(332): WP_Hook->apply_filters(NULL, Array)
    
    3 /home/antikua/antik.ua/www/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
    
    4 /home/antikua/antik.ua/www/wp-settings.php(480): do_action('plugins_loaded')
    
    5 /home/antikua/antik.ua/www/wp-config.php(100): require_once('/home/antikua/a…')
    
    6 /home/antikua/antik.ua/www/wp-load.php(50): require_once('/home/antikua/a…')
    
    7 /home/antikua/antik.ua/www/wp-blog-header.php(13): require_once('/home/antikua/a…')
    
    8 /home/antikua/antik.ua/www/index.php(17): require('/home/antikua/a…')
    
    9 {main}
    
    thrown in /home/antikua/antik.ua/www/wp-content/plugins/qtranslate-xt/qtranslate_core.php on line 102

    Looks like multilanguage plugin qTranslateXT produce this error (https://github.com/qtranslate/qtranslate-xt).

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hey Mikhail,

    I’ve tried to disable my own ‘jquery-3-6-0.min.js’ and get same error, but this time it’s default wordpress ‘jquery.min.js’ file.

    Here, you can test on this website (search form at very top): https://antik.ua

    When you open website everything’s ok, jquery is working, but when you start to type something in search form, then in console log browser gives this error:

    POST https://antik.ua/?wc-ajax=aws_action 500 jquery-3-6-0.min.js:2

    And for default wordpress jquery same error but with different name of jquery file.

    POST https://antik.ua/?wc-ajax=aws_action 500 jquery.min.js:2

    Both files are exist on hosting:

    https://antik.ua/wp-content/themes/antik/js/jquery-3-6-0.min.js:2

    https://antik.ua/wp-includes/js/jquery/jquery.min.js

    Current PHP version is 8.2.1.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hey Mark, I’m closing this topic, since the problem was not in filter, but in multi currency settings, I’ve changed main currency in backend as ukrainian hryvnas, not the euro, recalculated the prices, and everything’s working fine.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Hey Mark,

    I have tried everything – cleared cache in product filter plugin, cleared cache in multicurrency plugin, recount prices, refreshed the lookup tables. Anything doesn’t help.

    Here’s what I have also noticed, that when I’m set for example lowest price in filter, for example “17860” ukrainian hryvnas – after ajax call the link in browser adds parameter “?min_price=17860” and because the default currency is euro, filter is trying to search products that starts not with 17860 hryvnas price, but with 17860 euros.

    And if I manually change the value in link to “?min_price=425” it shows me products that starts with price of 17860 hryvnas, based on currency rate 1 euro for 42 hryvnas.

    So maybe the problem is that product filter plugin doesn’t convert input price in right currency and just uses default, despite that default currency doesn’t uses in fron-end?

    I had same issue, here’s how I fixed it.

    My register sidebar function had “aside” blocks in before and after widget:

    register_sidebar(
    	array(
    		'id' => 'products_filter',
    		'name' => 'Filter',
    		'description' => 'A place for filters.',
    		'before_widget' => '<aside id="%1$s" class="%2$s">',
    		'after_widget' => '</aside>',
    		'before_title' => '<header><h4>',
    		'after_title' => '</h4></header>'
    	)
    );

    What I made, is just changed aside blocks to div and everything is working now:

    register_sidebar(
    	array(
    		'id' => 'products_filter',
    		'name' => 'Filter',
    		'description' => 'A place for filters.',
    		'before_widget' => '<div id="%1$s" class="%2$s">',
    		'after_widget' => '</div>',
    		'before_title' => '<div>',
    		'after_title' => '</div>'
    	)
    );

    У меня проблем с активацией нет, но при обновлении до 18.1 через админку WP – процесс виснет.

    Totally support this review, my shop has 60k+ products, my pageload before activating the plugin was 2-5 seconds, and after activating the plugin pageload becomes 12-30 seconds. It is all only after activating the plugin, I didn’t even start to manage and create translations.

    And it’s all with litespeed server, opcahe and mamcache enabled – all optimization on server side was made as maximum as possible.

    Conclusion: this plugin can’t handle shop|websites with more than 5 000 products|pages.

    Moreover, WPML has a great surpice for you – if you gonna buy a license – after year of using you will not be able to register new websites to get an activation key without renewal, even with old version of WPML that you have bought.
    Looks more like a scam, because they didn’t mention this information in pricing plans. On the purchase page you can clearly see that they give you 1 year of updates & “support” and “Websites you can register” is “Unlimited” – without any restriction to time or subscription plan.

    One more thing about “support” – just go to their website and read support threads – 70% of support is stupid question on question on question on question. They didn’t resolve anything.

    Here’s free alternatives that worked for me:
    qTranslate-XT – good for 1-2 translation languages (because they store all translation data in single post|term).
    subLanguage – good for more than 2 translation languages (because they store each translation data in custom fields).

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Great, thank you very much!

    Meanwhile I’ll try to use cron jobs.

    Thread Starter Oleg Komarovskyi

    (@komarovski)

    Благодарю вас и желаю всего наилучшего, ваши плагины супер! 🙂

Viewing 15 replies - 1 through 15 (of 42 total)