What about Deferring a localized script?

The solution is basically from this SO post:

When wordpress “localizes” a script, what it does is has php print out <script></script> tags with javascript objects in them that are then accessible within the DOM to the scripts you are “sending” the parameters to.

If I understand correctly, the extension of WP_Scripts simple adds a filter, referenced by the (arbitrary) handle, script_l10n, then sends that filtered variable, $110n through to the parent method, localize, which is where WPs array of arrays to “localize” gets sent.

class Filterable_Scripts extends WP_Scripts
{
    function localize( $handle, $object_name, $l10n )
    {
        $l10n = apply_filters( 'script_l10n', $l10n, $handle, $object_name );
        return parent::localize($handle, $object_name, $l10n);
    }
}

Then we replace $GLOBALS['wp_scripts'] with our new filterable one.

function my_filter_script_intlization() {
    $GLOBALS['wp_scripts'] = new Filterable_Scripts;
}
add_action( 'init', 'my_filter_script_intlization');

And now we can hook into the filter to modify the l10n string from the plugin (once we’ve used print_r() or something to figure out what it is).

function se108362_example_filter($l10n, $handle, $object_name ) {
    if('simple-locator' == $handle && 'wpsl_locator' == $object_name) {

        $phyt_i10n_settings = array(
            'mapTypeId' => 'roadmap',
            'mapTypeControl' => false,
            'zoom' => 8,
            'panControl' => false,
            'zoomControlOptions' => array('style' => '') // was google.maps.ZoomControlStyle.SMALL
            );


        $l10n['l10n_print_after'] = 'wpsl_locator.map_options=" . json_encode($phyt_i10n_settings);

        return $l10n;
    }
    return $l10n;
}

add_filter("script_l10n', 'se108362_example_filter', 10 , 3);

Then in the js I replace the l10n variables with my hard-coded ones:

wpsl_locator.map_options.zoomControlOptions.style = google.maps.ZoomControlStyle.SMALL;
wpsl_locator.map_options.styles = wpsl_locator.mapstyles;

For some reason the Filterable_Scripts sub-class seems to break the Advanced Custom Fields script loading:

public function my_filter_script_intlization() {
    //These exist here:
    var_dump($GLOBALS['wp_scripts']->registered['acf-field-group']);
    var_dump($GLOBALS['wp_scripts']->registered['acf-input']);
    $GLOBALS['wp_scripts'] = new \PhytJobs\FilterableScripts;
    // But now they are gone
    print_r(isset($GLOBALS['wp_scripts']->registered['acf-field-group']));
}

My workaround is to do this:

public function my_filter_script_intlization() {
    $acf_field_group = $GLOBALS['wp_scripts']->registered['acf-field-group'];
    $acf_input = $GLOBALS['wp_scripts']->registered['acf-input'];
    $GLOBALS['wp_scripts'] = new \PhytJobs\FilterableScripts;
    $GLOBALS['wp_scripts']->registered['acf-field-group'] = $acf_field_group;
    $GLOBALS['wp_scripts']->registered['acf-input'] = $acf_input;
}

But I’m wondering why the sub-classing is breaking it in the first place.

Someone suggested that the issue is caused by hooking the my_filter_script_intlization action too late, after $WP_Scripts has already been partly populated. I’m still a little unclear on how that works or why ACF would be the problem.

UPDATE, ACF only loads its scripts in Admin and the other plugin only l10n in the front end so I just wrapped the action and filter hook in a !is_admin test and ACF has nothing to complain about.