:::: MENU ::::

Using/Updating wp_localize_script() Dynamically

One of the greatest features of WordPress is its built-in function library that allows so much flexibility in web design.  Whether you are a plugin developer or theme designer, WordPress has functions that make your life a heck of a lot easier.

On occasion though, some of the functions that are super cool, could sometimes use a little tweaking. One of those functions is wp_localize_script().

Simply put, wp_localize_script: “Localizes a script, but only if script has already been added. Can also be used to include arbitrary Javascript data in a page.”

I usually find myself adding in “arbitrary Javascript data” in the page alongside my localization strings if they are needed at all.  A sample of the code used to generate the localized script looks like this:

[cc lang=”php”] __(‘Hello’),
‘world’ => __(‘world’)
);
wp_localize_script(‘enqueued-script’, ‘obj’, $localized_data);
?>[/cc]

Note that this function calls a previously enqueued script which is not covered in this tutorial.

WordPress will then print onto the final page a Javascript object that will look like this:

[cc lang=”html”][/cc]

From time to time, I have wanted to add in an element to this object dynamically, but if I decided to localize the script again prior to the page load, the output would look like this:

[cc lang=”html”][/cc]

wp_localize_script just adds the new data as a new line item regardless of whether or not the objects are the same. This is not ideal especially if there is the chance that it could grow any larger than just three elements in the object.

After much searching, I came up with a solution that does not require any hacking or changing of the WordPress core (yay!) and is actually fairly simple to implement.

First, before we call our wp_localize_script function, we need to check and see if any localized data exists in our script that we have already enqueued. To do that, we must access the global $wp_scripts; object and use the get_data() function:

[cc lang=”php”]
global $wp_scripts;
$data = $wp_scripts->get_data(‘obj’, ‘data’);
[/cc]

If the data is empty, we can go ahead and localize our script:

[cc lang=”php”]
if(empty($data)) {
wp_localize_script(‘enqueued-script’, ‘obj’, $localized_data);
}
[/cc]

However, if we have already localized the script and some data exists, we need to convert that into some useable data and add to it before putting it back. First, we are going to check if $data is an array. If not, lets convert it from the JSON format that it exists in. We will need to remove the last semicolon character and the “var obj = ” intro in order to convert it:

[cc lang=”php”]
if(!is_array($data)) {
$data = json_decode(str_replace(‘var obj = ‘, ”, substr($data, 0, -1)), true);
}
[/cc]

Then we can add the existing elements to our new array:

[cc lang=”php”]
foreach($data as $key => $value) {
$localized_data[$key] = $value;
}
[/cc]

Finally, we need to empty out the data that is currently localized and then localize our new array:

[cc lang=”php”]
$wp_scripts->add_data(‘enqueued-script’, ‘data’, ”);
wp_localize_script(‘enqueued-script’, ‘obj’, $localized_data);
[/cc]

Altogether, this looks like:

[cc lang=”php”]get_data(‘enqueued-script’, ‘data’);
if(empty($data)) {
wp_localize_script(‘enqueued-script’, ‘obj’, $localized_data);
}
else {
if(!is_array($data)) {
$data = json_decode(str_replace(‘var obj = ‘, ”, substr($data, 0, -1)), true);
}
foreach($data as $key => $value) {
$localized_data[$key] = $value;
}
$wp_scripts->add_data(‘enqueued-script’, ‘data’, ”);
wp_localize_script(‘enqueued-script’, ‘obj’, $localized_data);
}
?>[/cc]

In my example, the new Javascript object would look like this:

[cc lang=”html”][/cc]

Let me know if this helps you out in any way!


4 Comments

  • Reply chacha |

    Hi! Do you know if i can use this method to “update” nonces when a user logs in / logs out using ajax? (nonces are no longer verified)

  • Reply Celso Bessa |

    Totally helped us on concatenating woocommerce scripts on Fotografias Aéreas website for better pageload performance.

    We were concatenating them in just one script, but it was throwing JS errors as it was trying to find the parameters printed by the original script. So, after learning how to print them, we solved.

    Thanks!

So, what do you think ?