Automattic / babble

Multilingual WordPress done right.
https://wordpress.org/plugins/babble/
245 stars 50 forks source link

Make the language selector sticky for repeat visits #351

Closed mdrovdahl closed 6 years ago

mdrovdahl commented 8 years ago

It seems there are two sensible points to select a language on the frontend:

  1. implicit: based on some method of language detection
  2. explicit: based on a user taking action on the language selector

In case 1 above, if the user is content with the detected language and does not take an action to switch it...then yay! we guessed right. We could store that for future visits, or not. There's little cost/benefit either way.

In case 2 above, we (likely) guessed wrong and the user has taken an explicit action to change the language and we should honor that by storing it for repeat visits.

The language selector seems the most likely candidate for setting the cookie. Where to read the cookie on repeat visits? I don't know.

emrikol commented 8 years ago

I've got a possible solution that can be used to store and detect a selected language from the language selector. It's not much more than a band-aid, but I think a similar implementation could be worked into the language selector.

This is should be safe for static and cached pages since all of the cookie work is handled through Javascript.

function babble_save_selected_language( $params ) { 
    foreach ( $params as $param ) {
        if ( 'language-selector' === $param['id'] ) {
            $list = bbl_get_switcher_links();
            ?>
            <script type="text/javascript">
                function bbl_read_cookie( cookie_name ) {
                    // From http://www.quirksmode.org/js/cookies.html
                    var nameEQ = cookie_name + "=";
                    var ca = document.cookie.split(';');
                    for(var i=0;i < ca.length;i++) {
                        var c = ca[i];
                        while (c.charAt(0)==' ') c = c.substring(1,c.length);
                        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
                    }
                    return null;
                }

                // Convert URL to lang code
                function bbl_get_lang_from_url( url ) {
                    for ( bbl_url_lang in bbl_lang_selector ) {
                        if ( bbl_lang_selector[bbl_url_lang].href === url ) {
                            return bbl_url_lang;
                        }
                    }
                    return false;
                }

                var bbl_selected_content_lang = bbl_read_cookie( <?php echo wp_json_encode( 'wp-bbl_content_lang_' . COOKIEHASH ) ; ?> );
                var bbl_lang_selector = <?php echo wp_json_encode( $list ); ?>;
                var bbl_get_current_lang_code = <?php echo wp_json_encode( bbl_get_current_lang_code() ) ?>;

                jQuery(function($) {
                    $('#language-selector select').attr('onchange','').on( 'change', function( event ) {
                        var bbl_url_lang = bbl_get_lang_from_url( $(this).val() );

                        if ( false !== bbl_url_lang ) {
                            document.cookie = 'wp-bbl_content_lang_' + <?php echo wp_json_encode( COOKIEHASH ); ?> + '=' + bbl_url_lang + '; expires=' + <?php echo wp_json_encode( date('D, d M Y H:i:s e', current_time( 'timestamp' ) + ( 60 * 60 * 24 * 365 ) ) ); ?> + '; path=/';
                            document.location.href = bbl_lang_selector[bbl_url_lang].href;
                            event.preventDefault();
                            return false;
                        }
                    });
                });

                if ( bbl_get_current_lang_code !== bbl_selected_content_lang ) {
                    // Current lang and cookie lang don't match
                    if ( bbl_lang_selector[bbl_selected_content_lang] ) {
                        document.location.href = bbl_lang_selector[bbl_selected_content_lang].href;
                    }
                }
            </script>
            <?php
            break;
        }
    }
    return $params;
}
add_filter( 'dynamic_sidebar_params', 'babble_save_selected_language' );