JavaScript Localisation in WordPress

Recently on Twitter @iamcracks asked

Attention WordPress Wizards & Gurus. Is it possible to “get WordPress to write a custom field into a javascript variable”?

source

While I wouldn’t be so bold as to claim I’m either a wizard or a guru, I happen to know the answer to @iamcracks question.

A while back I wrote a two part tutorial on using JavaScript the WordPress way, the code below builds on that. The first step is to load the JavaScript in functions.php using wp_enqueue_script() as detailed in the earlier tutorial:

<?php
function brt_load_scripts() {
  if (!is_admin()) {
    wp_enqueue_script(
      'brt-sample-script', //handle
      '/path/2/script.js', //source
      null, //no dependancies
      '1.0.1', //version
      true //load in html footer
    );
  }
}

add_action('wp_print_scripts', 'brt_load_scripts');
?>

This outputs the html required for the JavaScript when wp_footer() is called in footer.php

Localising the script is done using the function wp_localize_script() it takes three variables:

  • $handle – (string) the handle defined when registering the script with wp_enqueue_script
  • $javascriptObject – (string) name of the JavaScript object that contains the passed variables.
  • $variables – (array) the variables to be passed

To pass the site’s home page and the theme directory, we’d add this function call below the wp_enqueue_script call above:

<?php
...
wp_localize_script('brt-sample-script', 'brtSampleVars', array(
  'url' => get_bloginfo('url'),
  'theme_dir' => get_bloginfo('stylesheet_directory')
  )
);
...
?>

The output html would be:

<script type='text/javascript'>
/* <![CDATA[ */
var brtSampleVars = {
  url: "http://bigredtin.com",
  theme_dir: "http://bigredtin.com/wp-content/themes/bigredtin"
};
/* ]]> */
</script>
<script type='text/javascript' src='/path/2/script.js?ver=1.0.1'></script>

Accessing the variables within JavaScript is done using the standard dot notation, for example brtSampleVars.theme_dir to access the theme directory.

Using a post’s custom fields is slightly more complicated so I’ll write out the code in full:

<?php
function brt_load_scripts() {
  if (is_singular()) {
    wp_enqueue_script(
      'brt-sample-script', //handle
      '/path/2/script.js', //source
      null, //no dependancies
      '1.0.1', //version
      true //load in html footer
    );

    the_post();
    $allPostMeta = get_post_custom();
    wp_localize_script('brt-sample-script', 'brtSampleVars',
    array(
      'petersTwitter' => $allPostMeta['myTwitter'][0],
      'joshsTwitter' => $allPostMeta['joshsTwitter'][0]
      )
    );
    rewind_posts();
  }
}

add_action('wp_print_scripts', 'brt_load_scripts');
?>

Only pages and posts have custom fields so the check at the start of the function has become is_singlular() to check the user is on either a post or a page, earlier we were testing if the user was anywhere on the front end. The arguments for wp_enqueue_script have not changed.

the_post() needs to be called to start the loop and initiate the $post object so the associated custom fields can be accessed in the following line and put in an array.

With the custom fields easily available, the information can then be passed to wp_localize_script() as earlier demonstrated. The final step is to rewind the loop so next time the_post() is called, from either single.php or page.php, the post data is available.

The html output from the sample above would be:

<script type='text/javascript'>
/* <![CDATA[ */
var brtSampleVars = {
  petersTwitter: "@pwcc",
  joshsTwitter: "@sealfur"
};
/* ]]> */
</script>
<script type='text/javascript' src='/path/2/script.js?ver=1.0.1'></script>

3 comments

  1. @pwcc … You SO ARE a Wizard/Guru of sorts. I’ll probably read this article again, again, and then one more time, before getting @soupgiant to implement it because I cannot.

    Thanks for time.

    1. Thanks, you’re very kind and of course we can help.

  2. Great writeup. I’ve been reading posts on localize_script and this was the first one where I saw all the pieces put together in a way I could follow.