4

So in WordPress 4.6 they added the localization to the jQuery datepicker to be automatic. I am posting here first because I am not sure if this is actually a bug with WP or if I am doing something wrong.

If I set my language in the settings to French then the datepicker correctly gets localized and shows the months etc in French. However, for a demo page I want to show this off and don't want to have the entire site set to French but instead just a single page. Here is what I am using:

function change_language( $locale ) {
    if ( is_page( 156 ) ) {
        return 'fr_FR';
    }
    return $locale;
}
add_filter( 'locale', 'change_language' );

It is correctly changing the locale of the page but is not actually loading the datepicker localization based on that locale. Here is a screenshot:

enter image description here

Is there some kind of timing issue here perhaps? Maybe I am using the wrong filter? Or is this possibly a WP bug?

Thanks for any help!

3
+100

I was able to successfully change the datepicker's strings to a different locale for a single page using the switch_to_locale() function introduced in WordPress v4.7.

switch_to_locale() will modify the global $wp_locale variable which is used by wp_localize_jquery_ui_datepicker(). Changing the locale with the locale filter alone does not overwrite $wp_locale.

/**
 * Use switch_to_locale() on a special page.
 * This needs to be done early.
 */
add_action( 'pre_get_posts', 'wpse_change_language' );
function wpse_change_language( $query ) {
    if ( $query->is_main_query() && $query->is_page( 156 ) ) {
        // This will change the global $wp_locale which
        // is used by wp_localize_jquery_ui_datepicker() for translations.
        switch_to_locale( 'fr_FR' );
    }   
}

Enqueue datepicker styles and scripts.

/**
 * Load jQuery datepicker scripts and styles.
 */
add_action( 'wp_enqueue_scripts', 'wpse_enqueue_datepicker' );
function wpse_enqueue_datepicker() {
    wp_enqueue_script( 'jquery-ui-datepicker' );

    // Using code.jquery.com for simplicity. Normally I'd use a local file.
    wp_register_style(
        'jquery-ui',
        'https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css'
    );
    wp_enqueue_style( 'jquery-ui' );

    // A simple datepicker initialization script.
    wp_enqueue_script(
        'wpse-datepicker',
        plugin_dir_url( __FILE__ ) . '/wpse-datepicker.js',
        [ 'jquery-ui-datepicker' ],
        false,
        true
    );
}

wpse-datepicker.js

/**
 * Attach a datepicker to our markup.
 */
jQuery( document ).ready(function( $ ) {
    $( "#datepicker" ).datepicker();
});

Shortcode (for demo purposes)

/**
 * A simple shortcode used for adding the markup for
 * the datepicker.
 */
add_shortcode( 'wpse_datepicker', 'wpse_datepicker' );
function wpse_datepicker() {
    // Start buffering output.
    ob_start(); 

    // Add some debugging info:
    echo '<p>The locale is: ' . get_locale() . '</p>';
    ?>

    <div id="datepicker"></div>

    <?php
    // Return output generated up to this point.
    return ob_get_clean();
}

Content of page with ID 156

Testing the datepicker:

[wpse_datepicker]

Test complete!

Also note that it is necessary to have the language files installed for whatever locale is being used. They can be automatically installed by selecting the appropriate language in the admin area under Settings > General > Site Language.

6
  • 1
    rather than hooking locale, and having to remove it to stop the infinite loop, i achieve the same by hooking pre_get_posts, since OPs usage was conditional to the page. – hwl Jun 7 '17 at 5:02
  • 1
    all good! I was jumping on after testing the same approach and saw you had it down. i'll add this resource for that new (4.7) Wp_Locale_Switcher class, too: (make.wordpress.org/core/2016/11/07/…) – hwl Jun 7 '17 at 5:12
  • 1
    Awesome, thank you! This worked for me. Any drawbacks to this approach I should be aware of? – Nick Young Jun 7 '17 at 15:21
  • 1
    Glad to hear, Nick! I just made a slight update, adding the is_main_query() check in pre_get_posts() (which I had initially forgotten, thanks @SarahCoding). I don't know of any drawbacks for the use case you've outlined. If you were going to do something using all languages, then it might be a good idea to download all languages preemptively which would address the performance hit that @SarahCoding brought up). – Dave Romsey Jun 7 '17 at 18:15
  • 1
    Cool thanks for the reply. Yeah I always forget to check the main query too, good addition. – Nick Young Jun 7 '17 at 18:27
1

WordPress loads default translated strings before loading theme functions.php file (see wp-settings.php#L394). Then, the locale filter doesn't affect the jQuery UI datepicker localization anymore.

There're some improvements I want to add to the answers of @DaveRomsey and @FrankPWalentynowicz:

1. Using switch_to_locale():

This method works for a specific locale if that locale exists in available languages of the global $wp_locale_switcher (see WP_Locale_Switcher#L78).

Since WP_Locale_Switcher uses get_available_languages() to retrieve available languages, if fr_FR haven't been downloaded before, we have to download it into WP_LANG_DIR before switching to it:

function wpse268774_change_language($query) {
    if ( $query->is_page(156) && $query->is_main_query() ) {
        if (!function_exists('wp_download_language_pack')) {
            require ABSPATH . 'wp-admin/includes/file.php';
            require ABSPATH . 'wp-admin/includes/translation-install.php';
            $downloaded = wp_download_language_pack('fr_FR');
            if ($downloaded) {
                switch_to_locale('fr_FR');
            } else {
                // Maybe do something...
            }
        }
    }
}
add_action( 'pre_get_posts', 'wpse268774_change_language' );

Pros:

  • You can use standard translations for entire page without having to translate anything manually.

Cons:

  • A heavy performance hit because we have to download language pack and reload entire translated strings.

I recommend you to use pre_get_posts hook with $query->{method}. is_page() alone may not works. You should not use page ID because it may be changed while importing.

2. Using $.datepicker.setDefaults( options ):

WordPress doesn't use languages from jQuery UI Project so the $.datepicker.setDefaults(jQuery.datepicker.regional["fr"]) method doesn't work. You must localize default options manually.

Let's checkout wp_localize_jquery_ui_datepicker() function added to the wp_enqueue_scripts hook (see default-filters.php#L435). Now, we have to do:

remove_action('wp_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000);

function wpse268774_localize_jquery_ui_datepciker() {
    global $wp_locale;

    if ( !is_page(156) || !wp_script_is( 'jquery-ui-datepicker', 'enqueued' ) ) {
        return;
    }

    // Convert the PHP date format into jQuery UI's format.
    $datepicker_date_format = str_replace(
        array(
            'd', 'j', 'l', 'z', // Day.
            'F', 'M', 'n', 'm', // Month.
            'Y', 'y'            // Year.
        ),
        array(
            'dd', 'd', 'DD', 'o',
            'MM', 'M', 'm', 'mm',
            'yy', 'y'
        ),
        get_option( 'date_format' )
    );

    // Got this string by switching to fr_FR.
    $datepicker_defaults = '{"closeText":"Fermer","currentText":"Aujourd\u2019hui","monthNames":["janvier","f\u00e9vrier","mars","avril","mai","juin","juillet","ao\u00fbt","septembre","octobre","novembre","d\u00e9cembre"],"monthNamesShort":["Jan","F\u00e9v","Mar","Avr","Mai","Juin","Juil","Ao\u00fbt","Sep","Oct","Nov","D\u00e9c"],"nextText":"Suivant","prevText":"Pr\u00e9c\u00e9dent","dayNames":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"dayNamesShort":["dim","lun","mar","mer","jeu","ven","sam"],"dayNamesMin":["D","L","M","M","J","V","S"],"dateFormat":"MM d, yy","firstDay":1,"isRTL":false}';

    wp_add_inline_script( 'jquery-ui-datepicker', "jQuery(document).ready(function(jQuery){jQuery.datepicker.setDefaults({$datepicker_defaults});});" );
}
add_action('wp_enqueue_scripts', 'wpse268774_localize_jquery_ui_datepciker', 10, 0);

Pros:

  • No performance hit

Cons:

  • Only localize jQuery UI Datepicker options. Other strings in your page won't be translated.
  • You may have to translate the jQuery UI Datepicker options manually.
1

Create page-156.php template with its content matching the page you use right now. Save it in your theme, where your standard page.php is located.

Download datepicker-fr.js from https://github.com/jquery/jquery-ui/tree/master/ui/i18n and store it in root of your site.

Replace inline script for datepicker widget with:

<script src="/datepicker-fr.js"></script>
<script>
  $( function() {
    $( "#datepicker" ).datepicker( $.datepicker.regional[ "fr" ] );
  } );
</script>

That's all needed, for your demo page, to display datepicker in French.

1
  • Added downloaded French localization script. Now it works as expected. – Frank P. Walentynowicz Jun 7 '17 at 20:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.